學習Flutter一段時間了,偶然看到大家都說狀態管理,多數人都是用redux,對於一個Android開發人員來說之前根本沒接觸過,於是開始瞭解redux
,之後又瞭解閒魚推出的fish_redux
,然後又看到Vadaski發表的一系列關於Flutter狀態管理的文章,包括Scoped Model
, Redux
, BLoC
,RxDart
,provide
(想了解的可以移步),看的是眼花繚亂。對於Redux,能看懂是怎麼寫的,但真要到應用的層面,感覺還是有些吃力,更不知道怎樣維護好它,一時間也不知道用什麼什麼適合自己。後來又接觸到google推薦的Provider,於是學習了下。接下來就用Provider來實現一個計數的例子。
第一步,新增Provider依賴
provider: ^2.0.1+1
複製程式碼
pub地址:pub.dev/packages/pr…
第二步,建立Model
import 'package:provider/provider.dart';
class Counter with ChangeNotifier {//1
int _count;
Counter(this._count);
void add() {
_count++;
notifyListeners();//2
}
get count => _count;//3
}
複製程式碼
簡單的一個Counter
物件,裡面只有一個欄位_count
- 這裡需要混入
ChangeNotifier
- 寫一個增加的方法,然後需要呼叫
notifyListeners();
這個方法是通知用到Counter
物件的widget重新整理用的。 get
方法
第三步,使用ChangeNotifierProvider
通常main()方法是這麼寫
main() {
runApp(MyApp());
}
複製程式碼
我們要監聽改變就要在MyApp()外面套一層,這個是全域性的,於是如下
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
main() {
runApp(ChangeNotifierProvider<Counter>.value(//1
notifier: Counter(1),//2
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: "Provider",
home: HomePage(),
);
}
}
複製程式碼
ChangeNotifierProvider
呼叫value()
方法,裡面傳出notifier
和child
notifier
設定了預設的Counter(1)
當然Provider不止提供了ChangeNotifierProvider
,還有Provider
,ListenableProvider
,ValueListenableProvider
,StreamProvider
,
具體可以看wiki.
如果想管理多個物件可以用MultiProvider
,如下
MultiProvider(
providers: [
Provider<User>.value(value: user),
Provider<Goods>.value(value: goods),
.....
],
child: someWidget,
)
複製程式碼
第四步,使用Provider獲取Counter的值
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Home"),
actions: <Widget>[
FlatButton(
child: Text("下一頁"),
onPressed: () =>
Navigator.push(context, MaterialPageRoute(builder: (context) {
return SecondPage();
})),
),
],
),
body: Center(
child: Text("${Provider.of<Counter>(context).count}"),//1
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Provider.of<Counter>(context).add();//2
},
child: Icon(Icons.add),
),
);
}
}
複製程式碼
- 用
Provider.of<Counter>(context).count
獲取_count
的值,Provider.of<T>(context)
相當於Provider去查詢它管理的Counter(1)
- 用
Provider.of<Counter>(context).add();
呼叫Counter()
中的add()
方法
同樣第二個頁面也這樣寫,如下
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("SecondPage"),
),
body: Center(
child: Text("${Provider.of<Counter>(context).count}"),//1
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Provider.of<Counter>(context).add();//2
},
child: Icon(Icons.add),
),
);
}
}
複製程式碼
這樣,當每個頁面都點選+號按鈕時,_count
便會+1,同時通知並更新到使用它的地方。
完整程式碼,copy後可直接執行
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
main() {
runApp(ChangeNotifierProvider<Counter>.value(
notifier: Counter(1),
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: "Provider",
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Home"),
actions: <Widget>[
FlatButton(
child: Text("下一頁"),
onPressed: () =>
Navigator.push(context, MaterialPageRoute(builder: (context) {
return SecondPage();
})),
),
],
),
body: Center(
child: Text("${Provider.of<Counter>(context).count}"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Provider.of<Counter>(context).add();
},
child: Icon(Icons.add),
),
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text(Provider.of<String>(context)),
),
body: Center(
child: Text("${Provider.of<Counter>(context).count}"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Provider.of<Counter>(context).add();
},
child: Icon(Icons.add),
),
);
}
}
class Counter with ChangeNotifier {
int _count;
Counter(this._count);
void add() {
_count++;
notifyListeners();
}
get count => _count;
}
複製程式碼
總結
看了那麼多狀態管理的,個人感覺Provider還是屬於簡單易用的,並且是google推薦的。但感覺還需要成長,讓大家認可。我這裡只是一個簡單的使用,有一些地方也沒講太清楚還請大家見諒,同時也希望和各位學習Flutter的同學互相交流進步。