初识Flutter的状态管理包Provider

276 阅读11分钟

dart语言中,new XXX(),new可以省略。

先从无状态组件StatelessWidget和有状态组件StatefulWidget说起,

StatelessWidget无状态组件:

import "package:flutter/material.dart";

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: <Widget>[
            MyStatelessWidget(data: "xxx"),
          ],
        ),
      ),
    );
  }
}

class MyStatelessWidget extends StatelessWidget {
  MyStatelessWidget({Key key, this.data}) : super(key: key);
  final data;

  @override
  Widget build(BuildContext context) {
    return Text(data, style: TextStyle(fontSize: 50));
  }

  // @override
  // void didUpdateWidget(MyStateful oldWidget) {
  //   super.didUpdateWidget(oldWidget);
  //   print("didUpdateWidget");
  // }
}

上面是非常简单的一段完整的代码,有几点要说明:

  1. 继承StatelessWidget类的组件只能被build渲染一次,即只会调用一次bulid函数,调用完一次后,此函数和Home类会出栈释放内存,而所渲染的组件则被挂载到渲染树上。
  2. datafinal关键字的原因是:正如第一条所理解,数据一旦被赋值,便不能被再次修改,去掉final会报错。也可以直接赋初始值对Text("xxx")
  3. 上面被注释掉的 生命周期函数 不能在的StatelessWidget无状态组件中使用,会报错,只能在StatefulWidget有状态组件中使用。

StatefulWidget有状态组件:

import "package:flutter/material.dart";

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: <Widget>[
            MyStatefulWidget(),
          ],
        ),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidget createState() => new _MyStatefulWidget();
}

class _MyStatefulWidget extends State<MyStatefulWidget> {
  String data = "data";
  @override
  Widget build(BuildContext context) {
    return Column(children: <Widget>[
      FlatButton(
          child: Text("+", style: TextStyle(fontSize: 50)),
          onPressed: () => {}),
      Text(data),
      FlatButton(
          child: Text("-", style: TextStyle(fontSize: 50)),
          onPressed: () => {}),
    ]);
  }

  //自定义的函数reSetState():
  void reSetState() {
    data = "newData"; //这样直接修改并不会重新被渲染。
    //必须在setState()函数中修改才能被重新渲染。
    setState(() {
      data = "newData";
    });
  }

  //生命周期函数:
  @override
  void didUpdateWidget(MyStatefulWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }
}

上面是非常简单的一段完整的代码,有几点要说明:

  1. 有状态组件中的data值可以被多次修改,但是直接修改data值并不会重新被build渲染一遍,而必须调用setState()函数才能重新渲染。
  2. 每渲染一次,都会调用一次build函数,也都会调用一次这个生命周期函数didUpdateWidget()
  3. 每次didUpdateWidget()的调用,都意味着MyStatefulWidget整个有状态组件将被重新渲染一遍。
  4. 正如第3条所理解,这意味着,如果Column容器中有无数个Text(data)的兄弟组件,每次didUpdateWidget()的调用,都会将其所有组件重新渲染一遍,这对性能有一定的影响。
  5. 然而,我们只是修改了Text(data)中的data数据,没必要带上其他的组件一起渲染吧,那么如何解决这问题呢?

这回Provider包就起作用了。

先从Text(data)组件说起,查看Text(data)组件源码,发现它继承了StatelessWidget

源码:

class Text extends StatelessWidget {
  const Text(
      this.data,
      ...省略其他源码...
  );
}
  • 也就是说,Text(data)是个StatelessWidget无状态组件,data参数只能赋值一次,???
  • 问题来了,data只能被赋值一次,那为什么在有状态组件中,Text(data)中的data能被修改?
  • 有两个原因:
  1. data是在有状态组件被定义的,在未调用setState()时,data的变动,和Text组件无关。带有初始值的Text组件挂载到渲染树上,一直未动。
  2. data在有状态组件中被修改时,调用setState()是将整个有状态组件重新渲染,而并非渲染单个Text组件。并非是将渲染树上的单个Text组件重新挂载,而是将整个有状态组件进行重新挂载。
  3. 那么我们修改data时,如何才能只重新渲染单个Text组件,而不去渲染整个有状态组件呢?

-----Provider-----开启观察者模式

观察谁?

拿上面的有状态组件为例:

String data = "data";
Widget build(BuildContext context) {
    return Column(children: <Widget>[
      FlatButton(
          child: Text("+", style: TextStyle(fontSize: 50)),
          onPressed: () => {}),
      Text(data),
      FlatButton(
          child: Text("-", style: TextStyle(fontSize: 50)),
          onPressed: () => {}),
    ]);
  }
  • data数据是动态的,我们对data值的修改必然是在父组件或祖父组件中进行修改,而Text组件和2个FlatButton组件是兄弟组件。因此我们要对这3个兄弟组件进行观察,我们可以直接观察Column组件。

-----跨组件共享数据-----

在观察之前,我们先介绍Provider的第二个作用:跨组件共享数据

我们有个需求:A组件和B组件有一个数据要相互访问。若这个数据定义中A组件中,B组件便无法访问,若定义在B组件中,A组件便无法访问。

那该如何做到跨组件访问呢?

上面我们已经对Column进行了观察,这意味着Column的所有的子组件已经在我们的掌控之中。

  • 在观察者观察前,我们要创建一个ChangeNotifier类,这个类代表了组件之间访问数据的中间层,观察者所观察的Column组件中所有数据都放到这个中间层类ChangeNotifier上,只要是被观察者所观察的组件,都能访问ChangeNotifier类,都能访问到这个类中的数据。

创建中间层类要继承ChangeNotifier,我们在里面存放一个count数据和两个函数:

class MyNotifier extends ChangeNotifier {
  int count = 0;

  add() {
    count++;
    print(count);
  }

  minus() {
    count--;
    print(count);
  }
}

-----启动观察-----

上面一直在提观察,观察的对象是Column组件,那么要如何进行观察呢?

我们需将Column组件包裹在观察者内:

String data = "data";
  @override
  Widget build(BuildContext context) {
    return MultiProvider(  //观察者
      providers: [
        ChangeNotifierProvider(create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(   //需要被观察的组件
        children: <Widget>[
          FlatButton(
              child: Text("+", style: TextStyle(fontSize: 50)),
              onPressed: () => {}),
          Text(data),
          FlatButton(
              child: Text("-", style: TextStyle(fontSize: 50)),
              onPressed: () => {}),
        ],
      ),
    );
  }

我们要实现的功能:点击“+”按钮,data加1,点击“-”按钮,data减1。

先将FlatButton抽离出来:

AddButton按钮只需渲染一遍,因此继承StatelessWidget

class AddButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
        child: Text("+", style: TextStyle(fontSize: 50)), onPressed: () => {});
  }
}

MinusButton按钮只需渲染一遍,因此继承StatelessWidget

class MinusButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
        child: Text("-", style: TextStyle(fontSize: 50)), onPressed: () => {});
  }
}

Text(data)中的数据需要被更改,因此留在MyStatefulWidget类中:

String data = "data";
  @override
  Widget build(BuildContext context) {
    return MultiProvider(  //观察者
      providers: [
        ChangeNotifierProvider(create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(   //需要被观察的组件
        children: <Widget>[
          AddButton() ,
          Text(data),
          MinusButton(),
        ],
      ),
    );
  }

整理后的完整代码:

import "package:flutter/material.dart";
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: <Widget>[
            MyStatelessWidget(data: "xxx"),
            MyStatefulWidget(),
          ],
        ),
      ),
    );
  }
}




//普通的无状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyStatelessWidget extends StatelessWidget {
  MyStatelessWidget({Key key, this.data}) : super(key: key);
  final data;

  @override
  Widget build(BuildContext context) {
    return Text(data, style: TextStyle(fontSize: 50));
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑




//被观察者观察的有状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidget createState() => new _MyStatefulWidget();
}

class _MyStatefulWidget extends State<MyStatefulWidget> {
  String data = "data";
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //观察者
      providers: [
        ChangeNotifierProvider(
            create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(
        //需要被观察的组件
        children: <Widget>[
          AddButton(),
          Text(data),
          MinusButton(),
        ],
      ),
    );
  }

  void reSetState() {
    data = "newData";
    setState(() {
      data = "newData";
    });
  }

  @override
  void didUpdateWidget(MyStatefulWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑





//中间层↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyNotifier extends ChangeNotifier {
  int count = 0;

  add() {
    count++;
    print(count);
  }

  minus() {
    count--;
    print(count);
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑





//单独抽离出来的2个无状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class AddButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text("+", style: TextStyle(fontSize: 50)),
      onPressed: () => {},
    );
  }
}

class MinusButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text("-", style: TextStyle(fontSize: 50)),
      onPressed: () => {},
    );
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

跨组件访问共享数据

哪个组件需要访问,哪个组件就引入下面这段代码(前提是其组件被观察者观察):

    MyNotifier mainProvider = Provider.of<MyNotifier>(context);

比如:

//单独抽离出来的2个无状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class AddButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);  //引入
    return FlatButton(
      child: Text("+", style: TextStyle(fontSize: 50)),
      onPressed: () => {mainProvider.add()},  //访问其方法
    );
  }
}

class MinusButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);// 引入
    return FlatButton(
      child: Text("-", style: TextStyle(fontSize: 50)),
      onPressed: () => {mainProvider.minus()},  //访问其方法
    );
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

在模拟器中点击加减按钮,控制台会print(count)打印出conut值,但是data数据没有改变,

我们再观察一下下面代码:


//被观察者观察的有状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidget createState() => new _MyStatefulWidget();
}

class _MyStatefulWidget extends State<MyStatefulWidget> {
  String data = "data";
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //观察者
      providers: [
        ChangeNotifierProvider(
            create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(
        //需要被观察的组件
        children: <Widget>[
          AddButton(),
          Text(data),
          MinusButton(),
        ],
      ),
    );
  }

  void reSetState() {
    data = "newData";
    setState(() {
      data = "newData";
    });
  }

  @override
  void didUpdateWidget(MyStatefulWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

Text(data)中的data使用的并不是中间层的数据,而是自身组件中的数据,

我们把String data = "data"reSetState()函数代码删掉,在build函数中添加:

   MyNotifier mainProvider = Provider.of<MyNotifier>(context);

并把Text(data)改为Text(mainProvider.count.toString())

但是发现运行会报错,原因是在观察者观察前,还没有把中间层创建出来,因此这里不能引用中间层。

但我们可以把Text(mainProvider.count.toString())也抽离出来,这样就可以在创建中间层之后引入MyNotifier了:

class TextWedget extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);
    return Text(mainProvider.count.toString());
  }
}

整理后的完整代码:

import "package:flutter/material.dart";
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: <Widget>[
            MyStatelessWidget(data: "xxx"),
            MyStatefulWidget(),
          ],
        ),
      ),
    );
  }
}




//普通的无状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyStatelessWidget extends StatelessWidget {
  MyStatelessWidget({Key key, this.data}) : super(key: key);
  final data;

  @override
  Widget build(BuildContext context) {
    return Text(data, style: TextStyle(fontSize: 50));
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑




//被观察者观察的有状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidget createState() => new _MyStatefulWidget();
}

class _MyStatefulWidget extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //观察者
      providers: [
        ChangeNotifierProvider(
            create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(
        //需要被观察的组件
        children: <Widget>[
          AddButton(),
          TextWedget(),
          MinusButton(),
        ],
      ),
    );
  }

  @override
  void didUpdateWidget(MyStatefulWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑




//中间层↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyNotifier extends ChangeNotifier {
  int count = 0;

  add() {
    count++;
    print(count);
  }

  minus() {
    count--;
    print(count);
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑




//单独抽离出来的3个无状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class TextWedget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);
    return Text(mainProvider.count.toString());
  }
}

class AddButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);
    return FlatButton(
      child: Text("+", style: TextStyle(fontSize: 50)),
      onPressed: () => {mainProvider.add()},
    );
  }
}

class MinusButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);
    return FlatButton(
      child: Text("-", style: TextStyle(fontSize: 50)),
      onPressed: () => {mainProvider.minus()},
    );
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

我们在模拟器中点击加减按钮,观察发现仍只是控制台打印数字,但模拟器data却没有改变。

这是因为我们只是修改了count的值,并没有要求让值重新渲染,调用notifyListeners()才能将修改的值重新渲染,notifyListeners()等价于setState()函数。

//中间层↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyNotifier extends ChangeNotifier {
  int count = 0;

  add() {
    count++;
    print(count);
    notifyListeners();  //重新渲染
  }

  minus() {
    count--;
    print(count);
    notifyListeners();  //重新渲染
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

但引出了几个问题:

  1. Text(mainProvider.count.toString())中包了一个可被修改的数据,但为什么TextWedget 要继承StatelessWidget,而不继承StatefulWidget,继承StatefulWidget反而会报错?
  • 答:依我的理解,可能是Provider开发者故意约束的吧,被观察者监控的组件,都不能继承StatefulWidget,这样让我们很清晰的认识到所有动态数据都存放到中间层里,而我们创建的组件都只需是静态的,省了性能又省事。
  1. 既然TextWedget继承了继承StatelessWidget,那么TextWedget是个无状态组件,只能被build渲染一次,因此Text(mainProvider.count.toString())数据被修改,并不会重新build渲染一遍TextWedget组件。而TextWedget的父组件MyStatefulWidget组件是有状态的组件,那么数据被修改,重新build渲染也只能重新渲染MyStatefulWidget整个组件,而渲染整个MyStatefulWidget组件,必然会调用MyStatefulWidget组件中的didUpdateWidget()函数,然而该函数并没有被调用,这是为什么呢?
  • 答:Text(mainProvider.count.toString())被修改,并没有将MyStatefulWidget整个组件重新渲染,而是由中间层来控制重新渲染。观察者监控着每个组件,这意味着一旦有数据被修改,被修改的数据所对应的组件将被中间层控制重新渲染。

既然只是中间层来控制重新渲染,那么我们可以把所有组件都继承StatelessWidget以便省事:

原来的StatefulWidget代码:

//被观察者观察的有状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidget createState() => new _MyStatefulWidget();
}

class _MyStatefulWidget extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //观察者
      providers: [
        ChangeNotifierProvider(
            create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(
        //需要被观察的组件
        children: <Widget>[
          AddButton(),
          TextWedget(),
          MinusButton(),
        ],
      ),
    );
  }

  @override
  void didUpdateWidget(MyStatefulWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

改成StatelessWidget形式:

class MyStatefulWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //观察者
      providers: [
        ChangeNotifierProvider(
            create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(
        //需要被观察的组件
        children: <Widget>[
          AddButton(),
          TextWedget(),
          MinusButton(),
        ],
      ),
    );
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

完整的代码:

import "package:flutter/material.dart";
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: <Widget>[
            MyStatelessWidget(data: "xxx"),
            MyStatefulWidget(),
          ],
        ),
      ),
    );
  }
}




//普通的无状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyStatelessWidget extends StatelessWidget {
  MyStatelessWidget({Key key, this.data}) : super(key: key);
  final data;

  @override
  Widget build(BuildContext context) {
    return Text(data, style: TextStyle(fontSize: 50));
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑




//被观察者观察的有状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

class MyStatefulWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //观察者
      providers: [
        ChangeNotifierProvider(
            create: (context) => MyNotifier()), //观察者所依赖的中间层,可依赖多个
      ],
      child: Column(
        //需要被观察的组件
        children: <Widget>[
          AddButton(),
          TextWedget(),
          MinusButton(),
        ],
      ),
    );
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑




//中间层↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class MyNotifier extends ChangeNotifier {
  int count = 0;

  add() {
    count++;
    print(count);
    notifyListeners();
  }

  minus() {
    count--;
    print(count);
    notifyListeners();
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑




//单独抽离出来的3个无状态组件↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class TextWedget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);
    return Text(mainProvider.count.toString());
  }
}

class AddButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);
    return FlatButton(
      child: Text("+", style: TextStyle(fontSize: 50)),
      onPressed: () => {mainProvider.add()},
    );
  }
}

class MinusButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyNotifier mainProvider = Provider.of<MyNotifier>(context);
    return FlatButton(
      child: Text("-", style: TextStyle(fontSize: 50)),
      onPressed: () => {mainProvider.minus()},
    );
  }
}
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

这回代码清晰多了。

本人刚入门不久,由于知识浅薄难以深入,此文章肯定很多地方理解的不准确,轻喷~