FlutterWeb-04-状态管理

426 阅读2分钟

本文代码地址:gitee.com/gyy_xiaobai…

一,Flutter的状态管理框架有很多,我们今天使用谷歌官方的 Provider

1, 第一步:在yaml中引入依赖,然后执行flutter pub get

provider: ^6.0.2

2,之后我们便可以使用Provider实现全局数据的共享(前端通常叫状态管理)

二,具体使用

Provider涉及的概念比较多,这里只分析项目中用到的

1,生产者介绍

> I,Provider,无监听效果的Provider

使用Provider对象,包装具体的Bean

void main() {
  runApp(Provider<Book>(
    create: (ctx) => Book(),
    child: const App(),
  ));
}
class Book{
  String bookName = "春秋";
  String authName = '孟子';
}

对Book值的赋值:(在HomePage赋值)

Provider.of<Book>(context, listen: false).bookName = "《诗》《书》《礼》《乐》";

对Book值的获取:(在HomePage获取)

Provider.of<Book>(context).bookName
> II,ChangeNotifierProvider,有监听效果的Provider

使用ChangeNotifierProvider对象,包装具体的Bean

void main() {
  runApp(ChangeNotifierProvider<Person>(
    create: (ctx) => Person(),
    child: const App(),
  ));
}
class Person with ChangeNotifier{
  String name = "name";
  int age = 0;
  addAge() {
    age = age + 1;
    notifyListeners();
  }
}

对Person值的赋值:(在LoginPage赋值) -------赋值的时候,一定要传listen: false---------

Provider.of<Person>(context, listen: false).addAge();

对Person值的获取:(在HomePage获取) -------获取的时候,listen可传false,可传true---------

Provider.of<Person>(context).age.toString()
> III,MultiProvider,当有多个bean需要全局管理,就需要用MultiProvider
void main() {
  runApp(
      MultiProvider(
        providers: [
          Provider.value(value: Book()),
          ChangeNotifierProvider(create: (context)=> Person())
        ],
        child: const App(),
      ));
}

对Bean的赋值,和取值,同上面 I, II

2,消费者介绍

> I, Provider.of(context)
Provider.of<Book>(context).bookName,

Book为不可监听的Bean,所以上面代码只可以获取值

Provider.of<Person>(context).age.toString()
Provider.of<Person>(context, listen: true).age

Person为可监听的Bean,上面代码可以获取值,而且还可以监听值得变化

> II,Consumer
Consumer<Person>(
    builder: (context, model, child) {
      debugPrint('Consumer------------build');
      return Text(
        model.age.toString(),
      );
    },
    child: const Text(
      'Consumer - 监听Bean的变化',
    ))

Consumer可监听Bean的变化,并重新执行Consumer的builder函数,构建Widget

> III,Consumer和Provider.of(context)的选择

1,对于无监听效果的Bean,使用Provider.of(context)

2,对于有监听效果的Bean,使用Consumer,尽量避免使用Provider.of(context),因为Provider.of(context)会导致整个Page的build重新执行

三,简单的封装

void main() {
  runApp(Store.init(const App()));
}
///全局的状态管理
class Store {
  static BuildContext? _context;
  static init(child) {
    return MultiProvider(
      child: child,
      providers: [
        //无监听效果的
        Provider.value(value: Book()),
        //有监听效果的
        ChangeNotifierProvider(create: (context)=> Person())
      ],
    );
  }
  static setContext(BuildContext context) {
    Store._context ??= context;
    return context;
  }
  //获取store<T>
  static T of<T>({ bool listen = false}) {
    return Provider.of<T>(_context!, listen: listen);
  }
}

企业微信截图_16479460851294.png

总结3步:

1,将所有的provider抽取到store文件

2,在mian.dart中,调用runApp(Store.init(const App())) 方法

3,在App的build方法中,调用Store.setContext(context);

然后,前面所有的Provider.of, 就可以换成Store.of,而且不用传上下文了
//Provider.of<Book>(context).bookName
//Store.of<Book>().bookName
debugPrint(Store.of<Book>().bookName);