Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 984385f

Browse files
feat: flutter_provider添加readme
1 parent 2bf7880 commit 984385f

File tree

1 file changed

+309
-10
lines changed

1 file changed

+309
-10
lines changed

‎flutter_provider/README.md

Lines changed: 309 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,315 @@
1-
# flutter_provider
1+
## 背景
2+
provider是Google I/O 2019大会宣布的现在官方推荐的状态管理方式,
3+
[provider](https://pub.dev/packages/provider),语法糖是InheritedWidget,它允许在小部件树中传递数据,允许我们更加灵活地处理数据类型和数据。
24

3-
A new Flutter project.
5+
## 为什么需要状态管理
6+
在进行项目的开发时,我们往往需要管理不同页面之间的数据共享,在页面功能复杂,状态达到几十个上百个的时候,我们会难以清楚的维护我们的数据状态,本文将以简单计数器功能使用状态管理来讲解如何在Flutter中使用provider这个状态管理框架
47

5-
## Getting Started
8+
## 为什么选择Provider
9+
上次为大家介绍了provide,然后provide就被弃用了,不过要从provide转provider学习成本也不高,要了解provide可以转[Flutter UI使用Provide实现主题切换](https://juejin.im/post/5ca5e240f265da30c1725021)
610

7-
This project is a starting point for a Flutter application.
11+
使用Provider访问数据有两种方式
12+
* 使用Provider.of<T>(context),简单易用,但是要数据发生变化时,会进行页面级别rebuild,相当于stfulWidget
13+
* 使用Consumer,Consumer比Provider.of<T>(context)复杂一点,但是对于app性能的提高却有些很好的作用,当状态发生变化时,widget树会更新指定的节点,极小程度进行控件刷新,不会进行整颗widget树的更新,详细看下文分析。
14+
* Provider有泛型的优势,相当于namespace的特性,使用过vuex的应该知道namespace的重要性,它将我们的状态分离开来
815

9-
A few resources to get you started if this is your first Flutter project:
16+
## 项目地址
17+
[flutter-provider](https://github.com/efoxTeam/flutter-ui), 可参考项目中使用provider方法
1018

11-
-[Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12-
-[Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
19+
## 效果
20+
![FistPage](https://user-gold-cdn.xitu.io/2019/7/14/16bf0a59fca69007?w=712&h=1420&f=png&s=183884)
1321

14-
For help getting started with Flutter, view our
15-
[online documentation](https://flutter.dev/docs), which offers tutorials,
16-
samples, guidance on mobile development, and a full API reference.
22+
![SecondPage](https://user-gold-cdn.xitu.io/2019/7/14/16bf0a641f492d0b?w=698&h=1406&f=png&s=153411)
23+
## 如何使用
24+
### 添加依赖
25+
查看 [pub-install](https://pub.dev/packages/provider)
26+
* 在pubspec.yaml中引入依赖
27+
``` dart
28+
dependencies:
29+
provider: 3.0.0+1 #数据管理层
30+
```
31+
* 执行
32+
``` dart
33+
flutter packages get
34+
```
35+
* 在需要使用的页面中引入
36+
``` dart
37+
import 'package:provider/provider.dart'
38+
```
39+
40+
### 创建model (这才第一步)
41+
新建 lib/store/object/CounterInfo.dart 文件
42+
43+
新建 lib/store/object/UserInfo.dart 文件
44+
45+
数据模型,就不贴出代码了
46+
47+
新建 lib/store/model/CounterModel.dart 文件
48+
``` dart
49+
import 'package:flutter/foundation.dart' show ChangeNotifier;
50+
import '../object/CounterInfo.dart';
51+
export '../object/CounterInfo.dart';
52+
53+
class Counter extends CounterInfo with ChangeNotifier {
54+
CounterInfo _counterInfo = CounterInfo(count: 0, totalInfo: TotalInfo(total: 2));
55+
56+
int get count => _counterInfo.count;
57+
TotalInfo get totalInfo => _counterInfo.totalInfo;
58+
59+
void increment () {
60+
_counterInfo.count++;
61+
notifyListeners();
62+
}
63+
64+
void decrement () {
65+
_counterInfo.count--;
66+
notifyListeners();
67+
}
68+
}
69+
```
70+
新建 lib/store/model/UserModelModel.dart 文件
71+
```
72+
import 'package:flutter/foundation.dart' show ChangeNotifier;
73+
import '../object/UserInfo.dart';
74+
export '../object/UserInfo.dart';
75+
76+
class UserModel extends UserInfo with ChangeNotifier {
77+
UserInfo _userInfo = UserInfo(name: '咕噜猫不吃猫粮不吃鱼');
78+
79+
String get name => _userInfo.name;
80+
81+
void setName (name) {
82+
_userInfo.name = name;
83+
notifyListeners();
84+
}
85+
}
86+
```
87+
通过mixin混入ChangeNotifier,通过notifyListeners通知听众刷新
88+
### 封装Store (没错,到这里已经要快完成所有步骤了)
89+
新建 lib/store/index.dart 文件
90+
``` dart
91+
import 'package:flutter/material.dart' show BuildContext;
92+
import 'package:provider/provider.dart'
93+
show ChangeNotifierProvider, MultiProvider, Consumer, Provider;
94+
import 'model/index.dart' show Counter, UserModel;
95+
export 'model/index.dart';
96+
export 'package:provider/provider.dart';
97+
98+
class Store {
99+
static BuildContext context;
100+
static BuildContext widgetCtx;
101+
102+
// 我们将会在main.dart中runAPP实例化init
103+
static init({context, child}) {
104+
return MultiProvider(
105+
providers: [
106+
ChangeNotifierProvider(builder: (_) => Counter()),
107+
ChangeNotifierProvider(builder: (_) => UserModel(),)
108+
],
109+
child: child,
110+
);
111+
}
112+
113+
// 通过Provider.value<T>(context)获取状态数据
114+
static T value<T>(context) {
115+
return Provider.of(context);
116+
}
117+
118+
// 通过Consumer获取状态数据
119+
static Consumer connect<T>({builder, child}) {
120+
return Consumer<T>(builder: builder, child: child);
121+
}
122+
}
123+
124+
```
125+
需要管理多个状态只需要在providers添加对应的状态
126+
127+
providers: [
128+
ChangeNotifierProvider(builder: (_) => Counter()),
129+
ChangeNotifierProvider(builder: (_) => UserModel(),)
130+
],
131+
132+
133+
### 定义全局的Provide (倒数第二)
134+
lib/main.dart 文件
135+
``` dart
136+
import 'package:flutter/material.dart';
137+
import 'package:flutter_provider/store/index.dart' show Store;
138+
import 'package:flutter_provider/page/firstPage.dart' show FirstPage;
139+
140+
void main () {
141+
runApp(MyApp());
142+
}
143+
144+
class MyApp extends StatelessWidget {
145+
@override
146+
Widget build(BuildContext context) {
147+
print('根部重建: $context');
148+
return Store.init(
149+
context: context,
150+
child: MaterialApp(
151+
title: 'Provider',
152+
home: Builder(
153+
builder: (context) {
154+
Store.widgetCtx = context;
155+
print('widgetCtx: $context');
156+
return FirstPage();
157+
},
158+
),
159+
)
160+
);
161+
}
162+
}
163+
```
164+
165+
### 建立页面 (完成)
166+
新建 lib/page/firstPage.dart 文件
167+
``` dart
168+
import 'package:flutter/material.dart';
169+
import 'package:flutter_provider/store/index.dart' show Store, Counter, UserModel;
170+
import 'package:flutter_provider/page/secondPage.dart' show SecondPage;
171+
172+
class FirstPage extends StatelessWidget {
173+
TextEditingController controller = TextEditingController();
174+
@override
175+
Widget build(BuildContext context) {
176+
print('first page rebuild');
177+
return Scaffold(
178+
appBar: AppBar(title: Text('FirstPage'),),
179+
body: Center(
180+
child: Column(
181+
children: <Widget>[
182+
Store.connect<Counter>(
183+
builder: (context, snapshot, child) {
184+
return RaisedButton(
185+
child: Text('+'),
186+
onPressed: () {
187+
snapshot.increment();
188+
},
189+
);
190+
}
191+
),
192+
Store.connect<Counter>(
193+
builder: (context, snapshot, child) {
194+
print('first page counter widget rebuild');
195+
return Text(
196+
'${snapshot.count}'
197+
);
198+
}
199+
),
200+
Store.connect<Counter>(
201+
builder: (context, snapshot, child) {
202+
return RaisedButton(
203+
child: Text('-'),
204+
onPressed: () {
205+
snapshot.decrement();
206+
},
207+
);
208+
}
209+
),
210+
Store.connect<UserModel>(
211+
builder: (context, snapshot, child) {
212+
print('first page name Widget rebuild');
213+
return Text(
214+
'${Store.value<UserModel>(context).name}'
215+
);
216+
}
217+
),
218+
TextField(
219+
controller: controller,
220+
),
221+
Store.connect<UserModel>(
222+
builder: (context, snapshot, child) {
223+
return RaisedButton(
224+
child: Text('change name'),
225+
onPressed: () {
226+
snapshot.setName(controller.text);
227+
},
228+
);
229+
}
230+
)
231+
],
232+
),
233+
),
234+
floatingActionButton: FloatingActionButton(
235+
child: Center(
236+
child: Icon(Icons.group_work)
237+
),
238+
onPressed: () {
239+
Navigator.of(context)
240+
.push(MaterialPageRoute(builder: (BuildContext context) {
241+
return SecondPage();
242+
}));
243+
// Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) {
244+
// return SecondPage();
245+
// }));
246+
},
247+
),
248+
);
249+
}
250+
}
251+
```
252+
新建 lib/page/secondPage.dart 文件
253+
```
254+
import 'package:flutter/material.dart';
255+
import 'package:flutter_provider/store/index.dart' show Store, Counter, UserModel;
256+
257+
class SecondPage extends StatelessWidget {
258+
@override
259+
Widget build(BuildContext context) {
260+
print('second page rebuild');
261+
return Scaffold(
262+
appBar: AppBar(title: Text('SecondPage'),),
263+
body: Center(
264+
child: Column(
265+
children: <Widget>[
266+
RaisedButton(
267+
child: Text('+'),
268+
onPressed: () {
269+
Store.value<Counter>(context).increment();
270+
},
271+
),
272+
Builder(
273+
builder: (context) {
274+
print('second page counter widget rebuild');
275+
return Text(
276+
'second page: ${Store.value<Counter>(context).count}'
277+
);
278+
},
279+
),
280+
RaisedButton(
281+
child: Text('-'),
282+
onPressed: () {
283+
Store.value<Counter>(context).decrement();
284+
},
285+
),
286+
],
287+
),
288+
),
289+
);
290+
}
291+
}
292+
```
293+
294+
细心的同学可以发现我在firstPage中使用获取数据状态全部都是通过Consumer来获取的,在firstPage中使用了两个store(Counter和UserModel)绑定了两个不同的weiget,好处就在于:
295+
* 我通过+或-进行数据修改时,只会对使用Counter数据模型的widget进行更新,通过点击change name按钮时修改了UserModel中的name,也只会对使用了UserModel的weiget进行更新
296+
* firstPage中在build中进行了print('first page rebuild');
297+
* 在显示数量的weiget中进行了print('first page counter widget rebuild');
298+
* 在显示昵称的weiget中进行了print('first page name Widget rebuild');
299+
300+
结果是first page rebuild只会在页面初始化的时候进行打印,而操作数据增减和name修改只会重新渲染对应的weiget,下图分别为单独进行一次数据修改和name修改后的控制台输出
301+
![firstPage的print](https://user-gold-cdn.xitu.io/2019/7/14/16bf0a37e16aaa23?w=792&h=124&f=png&s=21009)
302+
303+
* 在secondPage中对于数据的操作我通过Provider.value<T>(context)获取,使用较为方便简单,但是数据改变时,会发生页面级别刷新
304+
* secondPage中build进行了print('second page rebuild');
305+
* 在显示数量的weiget中进行了print('second page counter widget rebuild');
306+
307+
结果是second page rebuild会在页面初始化的时候进行打印,但每次数据修改时同样也会进行print
308+
![secondPage的print](https://user-gold-cdn.xitu.io/2019/7/14/16bf0a3fbe6e658b?w=824&h=130&f=png&s=27985)
309+
310+
综上,使用Provider.value<T>(context)会导致页面刷新,虽然flutter会自动优化刷新,但还是建议大家尽量使用Consumer去获取数据,可以获取最好app的性能提升
311+
312+
## 最后
313+
欢迎更多学习flutter的小伙伴加入QQ群 Flutter UI: 798874340
314+
315+
敬请关注我们正在开发的:[efoxTeam/flutter-ui](https://github.com/efoxTeam/flutter-ui)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /