プロバイダー3を4に変換した後にFlutterアプリがクラッシュする


8

Provider 4.0.1今日使用するようにFlutterアプリをアップグレードしようとしたところ、次のコードがnullに値を割り当てるとクラッシュしました。

これが私が変換しようとしているコードです。私はコンパイル済みのOKに変更SingleChildCloneableWidgetSingleChildStatelessWidgetただけです。

import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';

List<SingleChildStatelessWidget> providers = [
  ...independentServices,
  ...dependentServices,
  ...uiConsumableProviders
];

List<SingleChildStatelessWidget> independentServices = [
  Provider.value(value: Api()),
  Provider.value(value: Tbl()),
  Provider.value(value: Bill()),
  Provider.value(value: Sale()),
  Provider.value(value: Category()),
  Provider.value(value: Menu()),
];

List<SingleChildStatelessWidget> dependentServices = [
  ProxyProvider<Api, AuthenticationService>(
    update: (context, api, authenticationService) => AuthenticationService(api: api),
  ),
];

List<SingleChildStatelessWidget> uiConsumableProviders = [
  StreamProvider<User>(
    create: (context) => Provider.of<AuthenticationService>(context, listen: false).user,
  ),
    lazy: false
];

私はそれを次のように実装しました:

StreamController<User> _userController = StreamController<User>();
Stream<User> get user => _userController.stream;

クラッシュは次の行で発生しました:

Future<void> _setFixedLanguageStrings(BuildContext context) async {

 User _user = Provider.of<User>(context);

 _user.homeString = await translate(context, 'Home');

ゲッター 'language'がnullで呼び出されました。レシーバー:null

これは問題Provider 3.0.3なく機能していましたが、明らかにもっと行う必要があります。

私の元のコードはこのチュートリアルから来ました 。

編集:lazy: falseストリームプロバイダーのcreateメソッドを追加して問題を修正しましたが、このコードの後半に別のエラーがあります。

Future<String> translate(BuildContext context, _term) async {

  final String _languageCode = Provider.of<User>(context).language;

このエラーが発生しました:

例外が発生しました。_AssertionError( 'package:provider / src / provider.dart':Failed assertion:line 213 pos 7: 'context.owner.debugBuilding || listen == false || _debugIsInInheritedProviderUpdate':プロバイダーで公開された値をリッスンしようとしました。ウィジェットツリーの外。

これは、を渡さずにProvider.ofを呼び出したイベントハンドラー(ボタンのonPressedなど)が原因である可能性がありますlisten: false

修正するには、次のように記述します。Provider.of(context、listen:false);

ウィジェットツリーが値を気にしない場合、イベントハンドラーに関連付けられたウィジェットを無意味に再構築する可能性があるため、サポートされていません。)

listen: false上記の行に追加してその問題を修正したようですが、使用しようとした次のプロバイダーがこのエラーを生成しました:

ウィジェットツリーの外部から、プロバイダーで公開された値をリッスンしようとしました。

これは、を渡さずにProvider.ofを呼び出したイベントハンドラー(ボタンのonPressedなど)が原因である可能性がありますlisten: false

修正するには、次のように記述します。Provider.of(context、listen:false);

ウィジェットツリーが値を気にしない場合、イベントハンドラーに関連付けられたウィジェットを無意味に再構築する可能性があるため、サポートされていません。'package:provider / src / provider.dart':失敗したアサーション:213行目7: 'context.owner.debugBuilding || 聞く== false || _debugIsInInheritedProviderUpdate '

プロバイダーを呼び出して追加するすべてのインスタンスに移動する必要がありlisten: falseますか?私がFlutterでかなり新しいので、ドキュメントがのまばらなため、何が変更されたのか、そしてその理由を誰かに説明してもらう必要がありProviderます。コードでプロバイダーを呼び出すことがよくありますが、この最後のエラーではコードの場所が返されませんでした。

されlisten: false、それは以前にはなかったとき、今常に必要か、私が何かを見逃していますか?プロバイダー変数をインスタンス化するすべての呼び出しにlisten:falseを追加し始め、それが機能しているように見えますが、これは正しいアプローチですか?listen: falseへのすべての呼び出しに追加しProvider.ofて、1日で呼び出す必要がありますか?

このエラーは、アプリがウィジェットツリー外の値をリッスンしようとしたが、ウィジェットのビルドメソッド内で呼び出したため、そうではないことを示しています。このエラーが正しい場合、どういうわけかすべてのプロバイダーはウィジェットツリーの外にあります。コードは2か月間問題なく機能しており、リッスンエラーはこの更新でのみ表面化しました。


アップデート時に同じ問題が発生しました。ウィジェットツリーを変更できる場合と変更できない場合はどうなりますか?私はロールバックしています。
Dpedrinha

回答:


3

私は同じ「問題」をlisten: false抱えています。プロバイダーを呼び出すすべての場所に追加すると、問題はなくなりましたが、それが正しい解決策かどうかわかりません...?


なぜlisten: falseデフォルトではないのSingleChildStatelessWidgetでしょうか?
markhorrocks

listen:falseでエラーはありませんが、UIは更新されないため、機能させるために何か他のものが必要です
Shakle

1

listen : false データがUIで何も更新しないときに呼び出され、ボタンをクリックしたときにウィジェット内のすべてのカードを削除するなど、使用する必要があります。

詳細については、こちらのgo_to_linkをご覧ください


0

listen:true デフォルトであることは論理的です。

論理的ではないイベントハンドラの内部を指定していません。listen: false

また、4.1.0はなんらかの方法でProvider.ofの代わりに使用できます。

context.read<T>() // Provider.of<T>(context, listen: false)
context.watch<T>() // Provider.of<T>(context)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.