あなたは消費者がわからない場合は、私のブログの記事、上に移動してくださいフラッタープロバイダのステータス管理-Consumerを、この記事では、過去の基盤に基づいています。
私たちは、地元のUIは、ページを更新誘惑には伝統的なSETSTATEを落下し、UIのパフォーマンスに段差を作る達成することができ、以前の消費者から知っています。しかし、私は、実際のビジネスのシナリオで消費者は多くの問題が発生しました使用しています。
栗の場合:
カウンタページは、これは、2つのテキストを持っているので、私たちは、ボタン1とボタンあり、[テキスト1]と[テキスト2]、および2つのボタンと命名した、シンプルなページカウンタではありません。テキスト1変更Button2の変更テキスト2]の値を変更するにはButton1をクリックして、同じCounterProviderですが、我々は2つのだけのデータを保持する値を変更することで、我々はそれが再描画を願っています。この時間が唯一のテキスト1、テキスト2は変わらないButton1をクリックしてくださいしかし、現実は冷却されます。。。
私たちは、限り、値が変更されたとして、それがホストリフレッシュUIを通知します、CounterProviderを取得するために消費者を使用しています。だから、[テキスト1]と[テキスト2]再描画の結果、特定のコードでの外観をできるようになるいずれかのボタンをクリックしてください
1.counter_provider.dart
import 'package:flutter/material.dart';
class CounterProvider with ChangeNotifier {
int _count = 0;
int _count1 = 100;
int get value => _count;
int get value1 => _count1;
void increment() {
_count++;
notifyListeners();
}
void increment1() {
_count1++;
notifyListeners();
}
}
そして、変数_count1のincrement1を()増加させる方法、および適切なgetメソッドを提供
2.my_page.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter_provider.dart';
class MyPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => MyPageState();
}
class MyPageState extends State<MyPage> {
///初始化CounterProvider
CounterProvider _counterProvider = new CounterProvider();
@override
Widget build(BuildContext context) {
print('页面重绘了。。。。。。。。。。。');
//整个页面使用ChangeNotifier来包裹
return ChangeNotifierProvider(
builder: (context) => _counterProvider,
child:
//child里面的内容不会因为数据的改变而重绘
Scaffold(
appBar: AppBar(
title: Text('my page'),
),
body: Center(
child:
//使用Cousumer来获取Provider
Column(
children: <Widget>[
//使用Consumer来获取CounterProvider,为Text提供数据
Consumer(builder: (BuildContext context,
CounterProvider counterProvider, Widget child) {
print('Text1重绘了。。。。。。');
return Text(
//获取数据
'Text1 : ${counterProvider.value}',
style: TextStyle(fontSize: 20),
);
}),
//使用Consumer来获取CounterProvider,为Text提供数据
Consumer(builder: (BuildContext context,
CounterProvider counterProvider, Widget child) {
print('Text2重绘了。。。。。。');
return Text(
//获取数据
'Text2 : ${counterProvider.value1}',
style: TextStyle(fontSize: 20),
);
}),
RaisedButton(
onPressed: () {
print('Button 1被点击了。。。。。。。。。。');
_counterProvider.increment();
},
child: Text('Button1'),
),
RaisedButton(
onPressed: () {
print('Button 2被点击了。。。。。。。。。。');
_counterProvider.increment1();
},
child: Text('Button2'),
)
],
)),
),
);
}
}
個別に包まれた2による消費者テキスト1とテキスト2は、我々は効果があると思います。
- print文が実行されていないテキスト1、テキスト2再描画のButton1原因をクリックしてください
- ボタン2は、テキスト2の再描画を引き起こしクリックし、[テキスト1]は、print文で実行されていません
私たちは、実際の状況を見て:
ときbutton1をクリックします
ときにクリックボタン2
かどうかは、ボタンが明確に違反した使用のプロバイダへの我々の意図で[テキスト1]と[テキスト2]、再描画が発生しますクリックしてください。実際の使用シナリオでは、このような状況は、UIのより悪い予想以上のパフォーマンスをもたらすでしょう。
プロバイダは、疑いもこの問題を発見し、それはこのような問題を解決するためのセレクタを立ち上げ、デザイナー。
セレクタに消費者に取って代わるだろう、私たちはカウンターのデモを変換してみましょう。国際的な慣行は、第1のセレクタのコンストラクタを見てみましょう:
Selector({
Key key,
//当父widget请求更新或者selector的返回值与之前的返回值不一样时会调用builder
@required ValueWidgetBuilder<S> builder,
//selector返回具体的值,返回的值必须继承自==而且不能为null
@required S Function(BuildContext, A) selector,
Widget child,
}) : assert(selector != null),
super(
key: key,
builder: builder,
selector: (context) => selector(context, Provider.of(context)),
child: child,
);
消費者、消費者よりも粒径が細かいのセレクタ制御すべてのデータは、セレクタは、1 /値の変化であるリスニング、リスニングでプロバイダを変更します。特定のコード:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter_provider.dart';
class MyPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => MyPageState();
}
class MyPageState extends State<MyPage> {
///初始化CounterProvider
CounterProvider _counterProvider = new CounterProvider();
@override
Widget build(BuildContext context) {
print('页面重绘了。。。。。。。。。。。');
//整个页面使用ChangeNotifier来包裹
return ChangeNotifierProvider(
builder: (context) => _counterProvider,
child:
//child里面的内容不会因为数据的改变而重绘
Scaffold(
appBar: AppBar(
title: Text('my page'),
),
body: Center(
child:
//使用Cousumer来获取Provider
Column(
children: <Widget>[
//用Selector替换Consumer
Selector(
builder: (BuildContext context, int data, Widget child) {
print('Text 1 重绘了。。。。。。。。。。');
return Text(
//获取数据
'Text1 : ${data.toString()}',
style: TextStyle(fontSize: 20));
}, selector:
(BuildContext context, CounterProvider counterProvider) {
//这个地方返回具体的值,对应builder中的data
return counterProvider.value;
}),
Selector(
builder: (BuildContext context, int data, Widget child) {
print('Text 2 重绘了。。。。。。。。。。');
return Text(
//获取数据
'Text2 : ${data.toString()}',
style: TextStyle(fontSize: 20),
);
},
selector: (BuildContext context,
CounterProvider counterProvider) {
return counterProvider.value1;
}),
RaisedButton(
onPressed: () {
print('Button 1被点击了。。。。。。。。。。');
_counterProvider.increment();
},
child: Text('Button1'),
),
RaisedButton(
onPressed: () {
print('Button 2被点击了。。。。。。。。。。');
_counterProvider.increment1();
},
child: Text('Button2'),
)
],
)),
),
);
}
}
上記のコードの形質転換後、私たちは、その後、ボタンの効果を見て、あなたは明確にButton1のが唯一のテキスト1を描画するためにつながるクリック参照することができ、ボタン2は、消費者がピット完璧なソリューションを残し、これまでテキスト2を描画するためにリードを灰色で表示し、クリックしてください!!
思考:
コードが使用中である前に、子供の体内の足場は、中心成分であり、我々は消費者センターに住んでいれば効果であるものに包まれましたか?ボタンをクリックしても、部分的更新は、上記のようなものの他のコンポーネントに影響を与えませんよう?以下に示す擬似コード
//用Consumer把selector包裹起来,Consumer和两个Selector都用的是CounterModel
Consumer(builder: (_, counterProvider, _) {
return Column(
children: <Widget>[
Selector(builder: (_, value, _) {
return Text(value);
}, selector: (_, counterProvider) {
return counterProvider.value;
},),
Selector(builder: (_, value1, _) {
return Text(value1);
}, selector: (_, counterProvider) {
return counterProvider.value1;
},),
],
)
});
セレクタと消費者は、CounterProviderで使用されているセレクタモニタ値の変化は、Cousumerページを聞くことができるならば、それは消費者が部品のパッケージ全体を再描画トリガするための答えは、ノーです。
もう一つの質問:
私は、最も外側のセレクタリスニングの値を制御すること、およびボタン3を消費者セレクタを交換する場合は、次のように疑似コードは次のとおりです。
//selector中还包含了两个子selector
Selector(
builder: (_, value2, _) {
return Column(
children: <Widget>[
//这个Text使用了value2
Text(value2),
Selector(
builder: (_, value, _) {
return Text(value);
},
selector: (_, counterProvider) {
return counterProvider.value;
},
),
Selector(
builder: (_, value1, _) {
return Text(value1);
},
selector: (_, counterProvider) {
return counterProvider.value1;
},
),
],
);
},
selector: (_, counterProvider) {
return counterProvider.value2;
},
);
結果を見てください
我々は唯一のText1再描画を見たときにButton1をクリックします
唯一のテキスト2が再描画時にボタン2をクリックして、
ボタン3時間をクリックすると、セレクタは、再描画が避けられないので、最も外側の、その子に属しても、テキスト1とテキスト2]による全体コンテンツを、再描画ラップが発生します
可能な限り小さく、そのうちのいくつかのラップサイズをセレクタを使用しているとき、我々はまた、注意を払っているので、消費者がよりそう。実際のプロジェクトの選択を使用する方法についてはあなたが見るものを教えてください。
まあ、ほとんどこれらのことを、私が通信するために問題がある場合、一緒に学ぶことを願っています!そこください正しい私と一緒に間違っています