Флаттер и дротик и будущее.Это известная особенность Dart Futures и null? - PullRequest
2 голосов
/ 27 июня 2019

В приведенном ниже коде (Windows Dart 2.4.0) возвращение пустого значения из будущего, которое указывает тип возвращаемого значения String, приводит к:

I/flutter ( 8735): The following assertion was thrown building Builder:
I/flutter ( 8735): type 'Future<dynamic>' is not a subtype of type 'Future<String>'

Если я возвращаю "null as String;", VSCode показывает предупреждение "ненужное приведение", однако код работает, и я не получаю фатальную ошибку. Кодекс ниже. Я закомментировал строку, которая вызывала проблему, и теперь возвращаю "null as String". Я использую пустую строку в Dart все время без проблем, поэтому она кажется только проблемой Futures AFAIK. Это просто известный факт о Dart и Futures, и это обходной путь («вернуть ноль как строку»)?

 @override
  void initState() {
    super.initState(); 
    Future<String> future = _initPreferences();
    future.then((sError) {
      if (sError != null) debugPrint("\n*** Error from initPrefs = $sError\n");
      if (sError == null) debugPrint("\n***Preferences were initialized OK\n");
    });
  }

  Future<String> _initPreferences() {
    return SharedPreferences.getInstance().then((prefs) {
      _prefs = prefs;
      //return null;
      return null as String;
    }).catchError((vError) {
      return "Unable to load categories";
    });
  }

Ответы [ 2 ]

0 голосов
/ 29 июня 2019

Вы не указали тип при использовании Future.then, поэтому он должен быть выведен. Поскольку вы возвращаете null, он не знает, какого типа он должен быть, поэтому ваш вызов Future.then не возвращает Future<String>.

Вы можете помочь движку вывода, явно указав тип через then<String>(...):

Future<String> _initPreferences() {
  return SharedPreferences.getInstance().then<String>((prefs) {
    _prefs = prefs;
    return null;
  }).catchError((vError) {
    return "Unable to load categories";
  });
}

хотя еще лучше было бы просто использовать async и await:

Future<String> _initPreferences() async {
  try {
    final prefs = await SharedPreferences.getInstance();
    _prefs = prefs;
    return null;
  } catch (vError) {
    return "Unable to load categories";
  }
}

Вот более простой случай воспроизведения:

Future<String> foo() {
  final future = Future(() => null);
  print('${future.runtimeType}');
  return future;
}

Future<void> main() async {
  await foo();
}

Я бы ожидал, что future будет Future<Null>, но вместо этого получится Future<dynamic>, и я не уверен почему. (Null является особенным и позволяет присваивать Future<Null> для Future<T>.) Я подозреваю, что это может быть ошибкой, поскольку dartanalyzer не генерирует никаких предупреждений об этом. (И вопреки тому, что говорится в некоторых комментариях, это не является чем-то новым для Dart 2.4.0; я пробовал использовать Dart 2.3.0, 2.3.2 и 2.4.0.) Я подал вопрос о он .

0 голосов
/ 28 июня 2019

Кто-то опубликовал то, что кажется правильным, но затем оно как-то исчезло, поэтому я не могу взять кредит. Весь смысл упражнения заключается в том, что я хочу использовать будущее (а не ждать). Ответ был / есть: (тогда)

 Future<String> _initPreferences() {
    return SharedPreferences.getInstance().then<String>((prefs) 
...