写点什么

【Flutter 专题】47 图解新的状态管理 Provider (二)

发布于: 9 小时前
【Flutter 专题】47 图解新的状态管理 Provider (二)

      小菜前几天学习了一下新的状态管理框架 ProviderProvier 支持多种类型的状态管理方式,小菜继续学习其余几种;

ListenableProvider 方式

1. 数据绑定

  1. ListenableProvider({Key key, @required ValueBuilder<T> builder, Disposer<T> 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')));  }}
复制代码


  1. 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. 获取数据

      小菜在上一篇博客中未曾提及,基本所有的获取数据方式基本相同且均支持两种方式;


  1. Provider.of(context) 方式


class ProviderText extends StatelessWidget {  @override  Widget build(BuildContext context) {    final user = Provider.of<User>(context);    return Text('${user.getName}');  }}
复制代码


  1. Consumer Widget 构造器方式


class ProviderText extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Consumer<User>(builder: (context, user, _) {        return Text(user.getName);      });  }}
复制代码

ValueListenableProvider 方式

      使用 ValueListenableProvider 方式时要注意,需要绑定的数据要继承自 ValueNotifier<T>,并实现其构造方法,通过对 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. 绑定数据

  1. ValueListenableProvider({Key key, @required ValueBuilder<ValueNotifier<T>> builder, UpdateShouldNotify<T> 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')));  }}
复制代码


  1. ValueListenableProvider.value({Key key, @required ValueListenable<T> valueListenable, UpdateShouldNotify<T> 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<T>()..sink.add() 输入需要处理的数据,通过 StreamController<T>()..stream 输出处理后的数据;整个过程都需要通过 StreamController 来控制;具体的单 stream 和多 stream 方式小菜稍后研究;

2. 绑定数据

  1. StreamProvider({Key key, @required ValueBuilder<StreamController<T>> 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(); }))))
复制代码


  1. StreamProvider.value({Key key, @required Stream<T> stream, T initialData, ..., Widget child })


      通过 .value 方式对 StreamControllerstream 进行数据绑定,同样需要在 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}');      })    ]));  }}
复制代码


小结

  1. 为方便理解,结合上一节的 ChangeNotifierProvider,发现与 ListenableProviderValueListenableProvider 的使用基本相同;


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 相似;


  1. 使用 ChangeNotifierProviderValueListenableProvider 绑定实体类时需要注意分别继承对应的 ChangeNotifierValueNotifier


class User with ChangeNotifier {}
class Person extends ValueNotifier<User> {}
复制代码


  1. 无论使用那种 .value 方式,均建议在 dispose 中进行 listener 的关闭;


@overridevoid dispose() {    stream.dispose();    super.dispose();}
复制代码



      小菜将 Provier 中提及的五种方式均尝试了一下,对于同一类的实体类也进行测试,如有错误请多多指导!


来源:阿策小和尚

发布于: 9 小时前阅读数: 2
用户头像

还未添加个人签名 2021.05.13 加入

Android / Flutter 小菜鸟~

评论

发布
暂无评论
【Flutter 专题】47 图解新的状态管理 Provider (二)