Flutter 47: 圖解新的狀態管理 Provider (二)
小菜前幾天學習了一下新的狀態管理框架 Provider,Provier 支援多種型別的狀態管理方式,小菜繼續學習其餘幾種;
ListenableProvider 方式
1. 資料繫結
- ListenableProvider({Key key, @required ValueBuilder builder, Disposer dispose, Widget child })
透過構造器繫結資料並進行監聽,當從 Widget Tree 中刪除時 dispose 要銷燬;注意:構造器 builder 不可為空;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListenableProvider<User>(
builder: (_) => User('Flutter', 0),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: 'Peovider Demo')));
}
}
- ListenableProvider.value({Key key, @required T listenable, Widget child })
透過 .value 方式對資料進行監聽 listenable;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListenableProvider<User>.value(
listenable: User('Flutter', 0),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: 'Peovider Demo')));
}
}
2. 獲取資料
小菜在上一篇部落格中未曾提及,基本所有的獲取資料方式基本相同且均支援兩種方式;
- Provider.of(context) 方式
class ProviderText extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
return Text('${user.getName}');
}
}
- Consumer Widget 構造器方式
class ProviderText extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<User>(builder: (context, user, _) {
return Text(user.getName);
});
}
}
ValueListenableProvider 方式
使用 ValueListenableProvider 方式時要注意,需要繫結的資料要繼承自 ValueNotifier,並實現其構造方法,透過對 value 的操作進行更新;小菜新建一個 person 實體類進行操作;
// 基本資料型別
class StringBean extends ValueNotifier<String> {
StringBean(String value) : super(value);
}
// 自定義實體類
class Person extends ValueNotifier<User> {
Person(User value) : super(value);
String get getPersonName => value.name;
void setPersonName(String name) {
value.name = name;
notifyListeners();
}
}
1. 繫結資料
- ValueListenableProvider({Key key, @required ValueBuilder<ValueNotifier> builder, UpdateShouldNotify updateShouldNotify, Widget child })
透過構造器繫結資料並進行監聽,且構造器 builder 不可為空;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ValueListenableProvider<User>(
builder: (_) => Person(User('person', 101)),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: 'Peovider Demo')));
}
}
- ValueListenableProvider.value({Key key, @required ValueListenable valueListenable, UpdateShouldNotify updateShouldNotify, Widget child })
透過 .value 方式對資料進行繫結監聽;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ValueListenableProvider<User>.value(
valueListenable: Person(User('person', 101)),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: 'Peovider Demo')));
}
}
2. 獲取資料
獲取資料的方式與上述基本一致;
class ProviderText extends StatelessWidget {
@override
Widget build(BuildContext context) {
final number = Provider.of<String>(context);
final person = Provider.of<User>(context);
return Center(
child: Column(children: <Widget>[
Text('${number.toString()}==${person.getName}'),
Consumer<User>(builder: (context, user, _) {
return Text(user.getName);
})
]));
}
}
StreamProvider 方式
1. Stream 簡介
Stream 存在於 Dart:async 庫中,主要用於處理非同步操作;在 ListView 展示網路介面資料時曾用到過;小菜對 Stream 的理解還不夠深入,基本理解為一個處理器,透過 StreamController()…sink.add() 輸入需要處理的資料,透過 StreamController()…stream 輸出處理後的資料;整個過程都需要透過 StreamController 來控制;具體的單 stream 和多 stream 方式小菜稍後研究;
2. 繫結資料
- StreamProvider({Key key, @required ValueBuilder<StreamController> builder, T initialData, …, Widget child })
透過構建器建立 StreamController 然後繫結資料,注意需要在 initialData 中初始化繫結資料;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamProvider<Teacher>(
builder: (_) => StreamController<Teacher>(),
initialData: Teacher('Teacher', 101),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: 'Peovider Demo')));
}
}
class Teacher {
var tname;
var tage;
Teacher(this.tname, this.tage);
}
Expanded(child: TextField(
onChanged: (changed) {
teacher.tname = changed;
teacher.tage = 150;
StreamController<Teacher>().sink.add(teacher);
},
controller: _phonecontroller,
decoration: InputDecoration(
hintText: '請輸入使用者名稱',
suffixIcon: IconButton(
icon: Icon(Icons.clear, color: Colors.black45),
onPressed: () {
_phonecontroller.clear();
}))))
- StreamProvider.value({Key key, @required Stream stream, T initialData, …, Widget child })
透過 .value 方式對 StreamController 的 stream 進行資料繫結,同樣需要在 initialData 中初始化資料;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamProvider<Teacher>.value(
stream: StreamController<Teacher>().stream,
initialData: Teacher('Teacher', 101),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: 'Peovider Demo')));
}
}
3. 獲取資料
class ProviderText extends StatelessWidget {
@override
Widget build(BuildContext context) {
final teacher = Provider.of<Teacher>(context);
return Center(
child: Column(children: <Widget>[
Text('${teacher.tname}'),
Consumer<Teacher>(builder: (context, teacher, _) {
return Text('${teacher.tname}==${teacher.tage}');
})
]));
}
}
小結
- 為方便理解,結合上一節的 ChangeNotifierProvider,發現與 ListenableProvider 和 ValueListenableProvider 的使用基本相同;
class ChangeNotifierProvider<T extends ChangeNotifier>
extends ListenableProvider<T> implements SingleChildCloneableWidget {}
class ChangeNotifier implements Listenable {}
class ValueListenableProvider<T>
extends AdaptiveBuilderWidget<ValueListenable<T>, ValueNotifier<T>>
implements SingleChildCloneableWidget {}
class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {}
分析原始碼:ChangeNotifierProvider 繼承自 ListenableProvider 且對應的 ChangeNotifier 繼承自 listenable;算是 ListenableProvider 的子類;ValueNotifier 繼承自 ChangeNotifier 也與 ChangeNotifierProvider 相似;
- 使用 ChangeNotifierProvider 和 ValueListenableProvider 繫結實體類時需要注意分別繼承對應的 ChangeNotifier 和 ValueNotifier;
class User with ChangeNotifier {}
class Person extends ValueNotifier<User> {}
- 無論使用那種 .value 方式,均建議在 dispose 中進行 listener 的關閉;
@override
void dispose() {
stream.dispose();
super.dispose();
}
小菜將 Provier 中提及的五種方式均嘗試了一下,對於同一類的實體類也進行測試,如有錯誤請多多指導!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2618/viewspace-2823007/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Flutter狀態管理Provider(二)過程分析FlutterIDE
- Flutter Provider狀態管理框架FlutterIDE框架
- flutter狀態管理provider的基本使用FlutterIDE
- Flutter | 狀態管理指南篇——ProviderFlutterIDE
- Flutter 狀態管理之 ChangeNotifierProvider(Provider)FlutterIDE
- Flutter狀態管理-04-ProviderFlutterIDE
- Flutter狀態管理:Provider4 入門教程(二)FlutterIDE
- Flutter狀態管理之Provider的理解使用FlutterIDE
- Flutter狀態管理Provider(四) Selector使用FlutterIDE
- Flutter狀態管理Provider,簡單上手FlutterIDE
- Flutter狀態管理Provider(三)基於Provider的程式碼框架FlutterIDE框架
- Flutter狀態管理provider的使用和封裝FlutterIDE封裝
- Flutter 全域性狀態管理之 Provider 初探FlutterIDE
- 使用 Provider 管理 Flutter 應用狀態 (下)IDEFlutter
- 使用 Provider 管理 Flutter 應用狀態 (上)IDEFlutter
- Flutter狀態管理Provider(一) 簡易使用FlutterIDE
- [譯]Flutter - 使用Provider實現狀態管理FlutterIDE
- Flutter 狀態管理框架 Provider 和 Get 分析Flutter框架IDE
- Flutter 狀態管理之 Redux,BLoC,Provider 的流程分析FlutterReduxBloCIDE
- Flutter狀態管理:Provider4 入門教程(一)FlutterIDE
- Flutter狀態管理:Provider4 入門教程(三)FlutterIDE
- Flutter開始干係列-狀態管理Provider3FlutterIDE
- Flutter Provider狀態管理---四種消費者使用分析FlutterIDE
- Flutter Provider狀態管理---八種提供者使用分析FlutterIDE
- Flutter | 狀態管理探索篇——Redux(二)FlutterRedux
- ⚠️Flutter的 狀態管理⚠️Flutter
- Flutter 知識梳理 (狀態管理) - Provider 之各種 XXProvider 的使用姿勢FlutterIDE
- 初略講解Flutter的狀態管理Flutter
- Flutter | 狀態管理Flutter
- Flutter狀態管理學習手冊(二)——ReduxFlutterRedux
- Flutter-狀態管理Flutter
- Flutter如何狀態管理Flutter
- 【Flutter 專題】87 初識狀態管理 Bloc (二)FlutterBloC
- Flutter 入門 - 狀態管理Flutter
- Flutter 狀態管理之BLoCFlutterBloC
- Flutter 狀態管理實踐Flutter
- Flutter入門 - 狀態管理Flutter
- 基於 Riverpod 的 Flutter 狀態管理Flutter