和尚前几天学习了一下新的状态管理框架 Provider,Provier 支持多种类型的状态管理方式,和尚继续学习其余几种;
通过构造器绑定数据并进行监听,当从 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')));
}
}
通过 .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')));
}
}
和尚在上一篇博客中未曾提及,基本所有的获取数据方式基本相同且均支持两种方式;
class ProviderText extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
return Text('${user.getName}');
}
}
class ProviderText extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<User>(builder: (context, user, _) {
return Text(user.getName);
});
}
}
使用 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();
}
}
通过构造器绑定数据并进行监听,且构造器 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')));
}
}
通过 .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')));
}
}
获取数据的方式与上述基本一致;
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);
})
]));
}
}
Stream 存在于 Dart:async 库中,主要用于处理异步操作;在 ListView 展示网络接口数据时曾用到过;和尚对 Stream 的理解还不够深入,基本理解为一个处理器,通过 StreamController()..sink.add() 输入需要处理的数据,通过 StreamController()..stream 输出处理后的数据;整个过程都需要通过 StreamController 来控制;具体的单 stream 和多 stream 方式和尚稍后研究;
通过构建器创建 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();
}))))
通过 .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')));
}
}
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}');
})
]));
}
}
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 相似;
class User with ChangeNotifier {}
class Person extends ValueNotifier<User> {}
@override
void dispose() {
stream.dispose();
super.dispose();
}
和尚将 Provier 中提及的五种方式均尝试了一下,对于同一类的实体类也进行测试,如有错误请多多指导!