Flutter - 状态管理

好久没更新了,=-= ·因为搞前端去了·抽空还是把自己学习的捋一下,状态管理简单的一些使用

InheritedWidget

可以实现跨组件数据的传递

  • 定义
    class HJCounterWidget extends InheritedWidget{
      /// 需要共享的状态
      final int counter;
    
      ///定义构造方法
      HJCounterWidget({this.counter, Widget child}): super(child:child);
    
      ///获取组件最近的当前InheritedWidget
      static HJCounterWidget of(BuildContext context){
        ///沿着Element树, 去找到最近的HYCounterElement, 从Element中取出Widget对象
        return context.dependOnInheritedWidgetOfExactType();
      }
    
      /// 必须实现的方法
      /// 如果返回true: 执行依赖当期的InheritedWidget的State中的didChangeDependencies
      /// 绝对要不要回调State中的didChangeDependencies
      @override
      bool updateShouldNotify(HJCounterWidget oldWidget) {
        // TODO: implement updateShouldNotify
        return oldWidget.counter != counter;
      }
    
    }
   
  • 使用
  class _HJStateTestPageState extends State{
  int _count = 100;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('状态管理'),
      ),
      body: HJCounterWidget(
          counter: _count,
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [HJShowData1(), HJShowData2()],
          ),
      )),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.data_usage),
        onPressed: (){
          setState(() {
            _count++;
          });
        },
      ),
    );
  }
}

class HJShowData1 extends StatefulWidget{
  @override
  State createState() {
    // TODO: implement createState
    return _HJShowData1State();
  }
}
class _HJShowData1State extends State{

  /// build 出来的widget 依赖的HJCounterWidget的数据发生改变时调用
  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();
    HJLog('_HJShowData1State didChangeDependencies', StackTrace.current);
  }

  @override
  Widget build(BuildContext context) {
    int counter = HJCounterWidget.of(context).counter;

    return Card(
      color: Colors.blue,
      child: Text('当前计数:$counter',style: TextStyle(fontSize: 20),),
    );
  }
}

class HJShowData2 extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    int counter = HJCounterWidget.of(context).counter;

    // TODO: implement build
    return Container(
      child: Text('当前计数:$counter',style: TextStyle(fontSize: 20)),
      color: Colors.amberAccent,
    );
  }
}
Provider

Provider是官方推荐的全局状态管理工具
主要看以下几个概念

  • ChangeNotifier:存数据的地方
  • ChangeNotifierProvider:提供数据的地方
  • Consumer:使用数据的地方
步骤
/**
 * 1.创建自己需要共享的数据
 * 2.在应用程序的顶层ChangeNotifierProvider
 * 3.在其它位置使用共享的数据
 *  > Provider.of: 当Provider中的数据发生改变时, Provider.of所在的Widget整个build方法都会重新构建
 *  > Consumer(相对推荐): 当Provider中的数据发生改变时, 执行重新执行Consumer的builder
 *  > Selector: 1.selector方法(作用,对原有的数据进行转换) 2.shouldRebuild(作用,要不要重新构建)
 */
举个栗子
  • 创建自己需要共享的数据
/// 1.创建自己需要共享的数据
/// 快捷键,选中类,cmd+n 自动生成get,set方法
class HJCounterViewModel extends ChangeNotifier {
  int _counter = 100;

  int get counter => _counter;

  set counter(int value) {
    _counter = value;
    notifyListeners();
  }
}
  • 在应用程序的顶层ChangeNotifierProvider
void main() {
  runApp(
    ChangeNotifierProvider(create: (ctx) {
      return HJCounterViewModel();
    },child: MyApp(),));
}
  • 在其它位置使用共享的数据,3种
1. int counter = Provider.of(context).counter;
2. Selector(
        selector: (ctx, counterVM)=>counterVM,
        shouldRebuild: (pre, next)=>false,/// 是否重新build
        builder: (ctx, counterVM, child){
          HJLog('builder ', StackTrace.current);
          return FloatingActionButton(
            child: Icon(Icons.data_usage),
            onPressed: (){
              counterVM.counter += 1;
            },
          );
        },
      ),
      
3. Consumer(
        builder: (ctx, counterVM, child){
            return FloatingActionButton(
              child: Icon(Icons.data_usage),
              onPressed: (){
                  counterVM.counter += 1;
              },
            );
        },
      ),
多个Provider
class HJUserViewModel extends ChangeNotifier {
  UserInfo _user;

  HJUserViewModel(this._user);

  UserInfo get user => _user;

  set user(UserInfo value) {
    _user = value;
    notifyListeners();
  }
}

class UserInfo {
  String name;
  int age;
  double height;

  UserInfo(this.name, this.age, this.height);
}

List providers = [
  ChangeNotifierProvider(create: (ctx) => HJUserViewModel(UserInfo('hj',18,180))),
  ChangeNotifierProvider(create: (ctx) => HJCounterViewModel())
];

void main() {
  /// 多个provider
  runApp(
    MultiProvider(
      providers: providers,
      child: MyApp(),
    )
  );
}
  • 使用同单个Provider,可以多个provider使用
Consumer2(builder: (ctx, userVM, counterVM, child){
        return Text(
              '当前计数:${counterVM.counter} - name:${userVM.user.name} age:${userVM.user.age} height:${userVM.user.height}',
              style: TextStyle(fontSize: 20, color: Colors.deepOrangeAccent),
              maxLines: 5,
            );
      })
  • 可能还有一些依赖关系,实际项目可以捋一捋
List providers = [
  // ChangeNotifierProvider(create: (ctx) => HJMealViewModel()),
  ChangeNotifierProvider(create: (ctx) => HJFilterViewModel()),
  ChangeNotifierProxyProvider(
      create: (ctx) =>HJMealViewModel(),
      update: (ctx,filterVM,mealVM){
        mealVM!.updateFilters(filterVM);
        return mealVM;
      }),

  ChangeNotifierProxyProvider2(
      create: (ctx) =>HJCollectViewModel(),
      update: (ctx,filterVM,mealsVM,collectVM){
        collectVM!.updateFilters(filterVM);
        collectVM.updateMeals(mealsVM);
        return collectVM;
      }
  )
];

你可能感兴趣的:(Flutter - 状态管理)