美文网首页Android开发经验谈一起来学Flutter~技术干货
Flutter 47: 图解新的状态管理 Provider (二

Flutter 47: 图解新的状态管理 Provider (二

作者: 阿策神奇 | 来源:发表于2019-06-03 19:58 被阅读37次

          小菜前几天学习了一下新的状态管理框架 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 的关闭;
    @override
    void dispose() {
        stream.dispose();
        super.dispose();
    }
    

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

          以下是小菜公众号,欢迎先来吐槽~


    公众号

    相关文章

      网友评论

        本文标题:Flutter 47: 图解新的状态管理 Provider (二

        本文链接:https://www.haomeiwen.com/subject/blfbtctx.html