ProviderパッケージがFlutterでどのように機能するかを理解するために作業していますが、listen:falseの機能について混乱しています。
新しいFlutterプロジェクトの通常のCounterサンプルを使用して、いくつかの基本的なコードを書きました。それぞれプロバイダーを使用して、3種類のステートレスウィジェットを作成しました。
3番目の例は、プロバイダーオブジェクトにアクセスし、再構築せずにそのオブジェクトのメソッドを呼び出す方法を示すことです。
アプリケーションを実行すると、すべてのウィジェットの数が変化します-最初の2つだけが変化すると予想しています。
これは簡単な例です-何がいけないのですか?
import 'package:flutter/material.Dart';
import 'package:provider/provider.Dart';
void main() => runApp(MyApp());
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(builder: (_) => Counter()),
],
child: MaterialApp(
title: 'Provider Demo',
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: MyHomePage(title: 'Provider Demo Home Page'),
),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
Counter counter = Provider.of<Counter>(context);
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ExampleProviderWidget(),
ExampleConsumerWidget(),
ExampleNoListenWidget()
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => counter.increment(),
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class ExampleProviderWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
Counter counter = Provider.of<Counter>(context);
return Container(
color: Colors.green,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Provider.of<Counter>(context):',
),
Text(
'${counter.count}',
style: Theme.of(context).textTheme.display1,
),
],
),
),
);
}
}
class ExampleConsumerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<Counter>(
builder: (context, counter, _) {
return Container(
color: Colors.blue,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Consumer<Counter>(context):',
),
Text(
'${counter.count}',
style: Theme.of(context).textTheme.display1,
),
],
),
),
);
},
);
}
}
class ExampleNoListenWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
Counter counter = Provider.of<Counter>(context, listen: false);
return Container(
color: Colors.red,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Provider.of<Counter>(context, listen: false):',
),
Text(
'${counter.count}',
style: Theme.of(context).textTheme.display1,
),
RaisedButton(
child: Text("Increment"),
onPressed: () => counter.increment(),
)
],
),
),
);
}
}
レミが提案したのは、実用的なアプローチ(ハック)です。しかし、この場合のより良い方法は、呼び出しCounter counter = Provider.of(context);を削除することだと思います。 MyHomePageClassから。その呼び出しはCounterオブジェクトのスコープを汚染しています。 flutter.ioで提案されているように、 コンシューマウィジェットをツリーのできるだけ奥に配置することをお勧めします 。 ExampleProviderWidget()、ExampleConsumerWidget()、ExampleNoListenWidget()で行ったように。したがって、floatingActionButtonを別個のウィジェットクラスにして、独自のProvider.of(context)を作成します。また、MyHomePageClassはProvider.ofを呼び出す必要はありません。