状态管理-Provider

2021-11-24  本文已影响0人  Jean_Lina

provider:官方推荐的全局状态管理工具
使用之前,先在pubspec.yaml引入对它的依赖 provider: ^6.0.0
使用步骤:
(1)创建ChangeNotifier,真正数据(状态)存放的地方

class DBJHomeViewModel extends ChangeNotifier {
  int _counter = 890;

  int get counter => _counter;

  set counter(int value) {
    _counter = value;
    // 通知所有的依赖者进行更新
    notifyListeners();
  }

  DBJHomeViewModel(this._counter);
}

(2)在Widget Tree中插入ChangeNotifierProvider,Widget树中提供数据(状态)的地方,会在其中创建对应的ChangeNotifier。将ChangeNotifierProvider放到了顶层,这样方便在整个应用的任何地方可以使用共享数据

main() {
  runApp(
    ChangeNotifierProvider(
      child: DBJMyApp(),
      create: (cxt) => DBJHomeViewModel(209), //共享数据
    ),
  );
}

(3)使用共享数据

获取共享数据方法:
😊 Provider.of<T>(context);

😁 Consumer<T>

😊 Selector<A, S>

Widget build(BuildContext context) {
    print('_DBJContentWidgetState 执行build');
    return Scaffold(
      appBar: AppBar(
        title: Text('状态管理-Consumer'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            DBJGoodsInfo(), //Provider 依赖数据展示
            SizedBox(height: 30),
            DBJShopCarInfo(), //Consumer 依赖数据展示
          ],
        ),
      ),
      floatingActionButton: buildFloatButtonWithConsumer(),
    );
  }
🍊 使用Consumer构建悬浮button:
  // 使用Consumer对共享数据进行修改
  Widget buildFloatButtonWithConsumer() {
    return Consumer<DBJHomeViewModel>(
      builder: (cxt, viewModel, child) {
        print('floatingActionButton Consumer 执行build');
        return FloatingActionButton(
          onPressed: () {
            print('点击++');
            //修改counter共享数据
            viewModel.counter++;
          },
          //直接引入Consumer的child,不进行新的构建
          child: child,
        );
      },
      child: Icon(Icons.inbox_rounded),
    );
  }
🍊 使用Selector构建悬浮button:
优化后:不依赖共享数据展示,只对共享数据进行修改
1:Provider.of<DBJHomeViewModel>(context, listen: false);
Widget buildFloatButtonWithProvider() {
    print('floatingActionButton 执行build');
    return FloatingActionButton(
      onPressed: () {
        print('点击++');
        DBJHomeViewModel viewModel =
        Provider.of<DBJHomeViewModel>(context, listen: false);
        viewModel.counter++; //修改counter共享数据
      },
      child: Icon(Icons.inbox_rounded),
    );
  }
2:使用Selector的shouldRebuild避免重复build
  Widget buildFloatButtonWithSelector() {
    return Selector<DBJHomeViewModel, DBJHomeViewModel>(
      selector: (cxc, viewModel) {
        return viewModel;
      },
      shouldRebuild: (previous, next) => false, // 不重新build
      child: Icon(Icons.inbox_rounded),
      builder: (BuildContext context, viewModel1, Widget? child) {
        print('floatingActionButton Selector 执行build');
        return FloatingActionButton(
          onPressed: () {
            print('点击++');
            viewModel1.counter++; //修改counter共享数据
          },
          child: child,
        );
      },
    );
  }
🍎 优化前(使用Provider获取数据,每次数据变化build方法重新执行)
class _DBJGoodsInfoState extends State<DBJGoodsInfo> {
  Widget buildWidgetWithProvider() {
    print('商品信息 执行build');
    int number = Provider.of<DBJHomeViewModel>(context).counter;
    return Card(
      child: Text(
        '商品信息:$number',
        style: TextStyle(fontSize: 18, color: Colors.purple),
      ),
    );
  }
🍎 优化后(使用Consumer获取数据减少build,每次数据变化仅Consumer内部的build方法重新执行)
  Widget buildWidgetWithConsumer() {
    print('商品信息 执行build');
    return Card(
      child: Consumer<DBJHomeViewModel>(
        builder: (BuildContext context, viewModel, Widget? child) {
          print('商品信息 Consumer 执行build');
          return Text(
            '商品信息:${viewModel.counter}',
            style: TextStyle(fontSize: 18, color: Colors.purple),
          );
        },
      ),
    );
  }
  @override
  Widget build(BuildContext context) {
    return buildWidgetWithProvider();
    return buildWidgetWithConsumer();
  }
}
🍎 最优方案(使用Selector,当viewModel中的其他数据发生变化,不依赖某个共享数据的其他widge,该build方法不会重新执行)
Widget buildPriceWidget() {
    print('价格信息 buildPriceWidget');
    return Selector<DBJHomeViewModel, DBJHomeViewModel>(
      selector: (cxt, vm) {
        return vm;
      },
      builder: (cxt, vm, child) {
        print('价格信息 Selector 执行build');
        return Container(
          child: Text(
            '价格信息:${vm.price}',
            style: TextStyle(fontSize: 18, color: Colors.green),
          ),
        );
      },
    );
  }
Simulator Screen Shot - iPhone 11 - 2021-11-24 at 12.15.56.png
截屏2021-11-24 下午12.16.06.png 12.png 截屏2021-11-24 下午3.04.28.png 截屏2021-11-24 下午3.03.25.png
截屏2021-11-24 下午3.23.02.png
上一篇 下一篇

猜你喜欢

热点阅读