Flutter 专题47 图解新的状态管理 Provider #yyds干货盘点#

Posted 阿策小和尚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 专题47 图解新的状态管理 Provider #yyds干货盘点#相关的知识,希望对你有一定的参考价值。

      小菜前几天学习了一下新的状态管理框架 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);
    
    
  2. 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 )**

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过构造器绑定数据并进行监听,且构造器 **builder** 不可为空;

class MyApp extends StatelessWidget br/>@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)));

2. **ValueListenableProvider.value(Key key, @required ValueListenable<T> valueListenable, UpdateShouldNotify<T> updateShouldNotify, Widget child )**

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过 **.value** 方式对数据进行绑定监听;

class MyApp extends StatelessWidget br/>@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. 获取数据
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;获取数据的方式与上述基本一致;

class ProviderText extends StatelessWidget br/>@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);
)
]));

![4701.gif](https://s2.51cto.com/images/20211227/1640568764211683.gif)

### StreamProvider 方式
#### 1. Stream 简介
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**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 )**

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过构建器创建 **StreamController** 然后绑定数据,注意需要在 **initialData** 中初始化绑定数据;

class MyApp extends StatelessWidget br/>@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();
))))

2. **StreamProvider.value(Key key, @required Stream<T> stream, T initialData, ..., Widget child )**

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过 **.value** 方式对 **StreamController** 的 **stream** 进行数据绑定,同样需要在 **initialData** 中初始化数据;

class MyApp extends StatelessWidget br/>@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 br/>@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);
)
]));

![4702.gif](https://s2.51cto.com/images/20211227/1640568752477209.gif)
### 小结
1. 为方便理解,结合上一节的 **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>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;分析源码:**ChangeNotifierProvider** 继承自 **ListenableProvider** 且对应的 **ChangeNotifier** 继承自 **listenable**;算是 **ListenableProvider** 的子类;**ValueNotifier** 继承自 **ChangeNotifier** 也与 **ChangeNotifierProvider** 相似;

2. 使用 **ChangeNotifierProvider** 和 **ValueListenableProvider** 绑定实体类时需要注意分别继承对应的 **ChangeNotifier** 和 **ValueNotifier**;

class User with ChangeNotifier

class Person extends ValueNotifier<User>

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

@override
void dispose()
stream.dispose();
super.dispose();


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

>  来源:阿策小和尚

以上是关于Flutter 专题47 图解新的状态管理 Provider #yyds干货盘点#的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 专题29 图解自定义底部状态栏 ACEBottomNavigationBar #yyds干货盘点#

Flutter 专题30 图解自定义底部状态栏 ACEBottomNavigationBar #yyds干货盘点#

Android:Flutter 专题03 图解第一个程序 Hello World

Flutter 专题89 图解基本 Overlay 悬浮新手引导 #yyds干货盘点#

Flutter 专题02 图解 Mac 环境下安装配置环境

Flutter 专题87 初识状态管理 Bloc #yyds干货盘点#