Flutter中的状态管理

InheritedWidget

  • 找到需要共用属性/模型的多个Widget的共有父Widget
  • 用自定义的InheritedWidget包裹该父类
  • 在子Widget内部通过context获取共有属性/模型,进行显示
  • 修改值的话,在共有父Widget的build方法内部修改变量值,重新赋值给自定义InheritedWidget即可
  • 通常用来共享数据

Demo示例(OSNavigator无需关心)

import 'package:flutter/material.dart';
import 'package:flutter_navigator/Core/OSState.dart';
import 'package:flutter_navigator/OSNavigator/OSNavigator.dart';

import 'Model/VideoModel.dart';

// 状态管理类
class AMCommonStateWidget extends InheritedWidget {
  final int count;
  AMCommonStateWidget({required this.count, required Widget child})
      : super(child: child);

  static AMCommonStateWidget? of(BuildContext context) {
    // 沿着Element树,去找最近的AMCommonStateElement, 从Element中取出Widget对象
    return context.dependOnInheritedWidgetOfExactType();
  }

  @override
  bool updateShouldNotify(covariant AMCommonStateWidget oldWidget) {
    // TODO: implement updateShouldNotify
    return oldWidget.count != count;
  }
}

class AMHomePage extends StatefulWidget {
  const AMHomePage({Key? key}) : super(key: key);
  @override
  _AMHomePageState createState() => _AMHomePageState();
}

class _AMHomePageState extends OSState<AMHomePage> {
  var listener;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    OSNavigator.getInstance().addListener(this.listener = (current, pre) {
      print("当前页面:${current.page}");
      print("上一个页面:${pre.page}");
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    OSNavigator.getInstance().removeListener(this.listener);
    super.dispose();
  }

  // 变量声明在 build方法外面,如果在build内部声明,重新build每次都会声明,相当于变量永远是新的,值永远是初始化的值
  var count = 15;
  Widget build(BuildContext context) {
    // 默认初始化10
    return Scaffold(
      appBar: AppBar(
        title: Text("逻辑资源"),
      ),
      body: AMCommonStateWidget(
        count: count,
        child: Column(
          children: [
            Container(
              height: 110,
              width: double.infinity,
              child: Card(
                color: Colors.orange,
                child: Column(
                  children: [
                    MaterialButton(
                      color: Colors.redAccent,
                      textColor: Colors.white,
                      onPressed: () {
                        OSNavigator.getInstance().onJumpTo(
                            RouteStatus.homeDetail,
                            args: {"videoModel": VideoModel(180)});
                      },
                      child: Text("点击跳转详情"),
                    ),
                    MaterialButton(
                      color: Colors.redAccent,
                      textColor: Colors.white,
                      onPressed: () {
                        // 修改变量
                        setState(() {
                          count++;
                        });
                      },
                      child: Text("计数器+1"),
                    ),
                  ],
                ),
              ),
            ),
            AMCardView01(),
            AMCardView02()
          ],
        ),
      ),
    );
  }
}

class AMCardView01 extends StatelessWidget {
  const AMCardView01({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var resCount = AMCommonStateWidget.of(context)?.count;
    resCount ??= 10;

    return Container(
      height: 80,
      width: double.infinity,
      child: Card(
        color: Colors.orange,
        child: Column(
          children: [
            Center(
              child: Text("当前的数量为$resCount"),
            )
          ],
        ),
      ),
    );
  }
}

class AMCardView02 extends StatelessWidget {
  const AMCardView02({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var resCount = AMCommonStateWidget.of(context)?.count;
    resCount ??= 10;

    return Container(
      height: 80,
      width: double.infinity,
      child: Card(
        color: Colors.yellow,
        child: Column(
          children: [
            Center(
              child: Text("当前的数量为$resCount"),
            )
          ],
        ),
      ),
    );
  }
}

Provider

  • 官方推荐的状态管理工具,相当重要
  • ChangeNotifier:真正数据(状态)存放的地方
  • ChangeNotifierProvider:Widget树中提供数据(状态)的地方,会在其中创建对应的ChangeNotifier
  • Consumer:Widget树中需要使用数据(状态)的地方
  • Provider.of:当Provider中数据发生改变时,Provider.of所在的Widget整个build方法都会重新构建
  • Consumer(相对推荐):当Provider中的数据改变时,Consumer的builder方法会重新构建
  • Selector: 1.selector方法(作用对原有数据进行转换)2.shouldRebuild(作用是否需要重新构建)

 

四步骤上手Provider

  1. 创建自己需要共享的数据
  2. 在程序的顶层创建ChangeNotifierProvider
  3. 在其他位置共享数据
  4. Consumer 修改数据通知更新(局部更新)
import 'package:flutter/material.dart';
import 'package:flutter_navigator/Core/OSState.dart';
import 'package:flutter_navigator/OSNavigator/OSNavigator.dart';
import 'package:provider/provider.dart';

import 'Model/VideoModel.dart';

/// 四步骤上手Provider
/// 1.创建自己需要共享的数据
/// 2.在程序的顶层创建ChangeNotifierProvider
/// 3.在其他位置共享数据
/// 4.Consumer 修改数据通知更新

//1.创建自己需要共享的数据
class AMCommonViewModel with ChangeNotifier {
  int _count = 10;
  int get count => _count;
  set count(int value) {
    _count = value;
    // 通知监听者,更新数据
    notifyListeners();
  }
}

class AMHomePage extends StatefulWidget {
  const AMHomePage({Key? key}) : super(key: key);
  @override
  _AMHomePageState createState() => _AMHomePageState();
}

class _AMHomePageState extends OSState<AMHomePage> {
  var listener;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    OSNavigator.getInstance().addListener(this.listener = (current, pre) {
      print("当前页面:${current.page}");
      print("上一个页面:${pre.page}");
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    OSNavigator.getInstance().removeListener(this.listener);
    super.dispose();
  }

  // 变量声明在 build方法外面,如果在build内部声明,重新build每次都会声明,相当于变量永远是新的,值永远是初始化的值
  Widget build(BuildContext context) {
    /// 2.在程序的顶层创建ChangeNotifierProvider(我这里仅限HomePage,如果需要最顶层,可以包裹runApp)
    return ChangeNotifierProvider(
      create: (ctx) => AMCommonViewModel(),
      child: Scaffold(
        appBar: AppBar(
          title: Text("逻辑资源"),
        ),
        body: Column(
          children: [
            Container(
              height: 110,
              width: double.infinity,
              child: Card(
                color: Colors.orange,
                child: Column(
                  children: [
                    MaterialButton(
                      color: Colors.redAccent,
                      textColor: Colors.white,
                      onPressed: () {
                        OSNavigator.getInstance().onJumpTo(
                            RouteStatus.homeDetail,
                            args: {"videoModel": VideoModel(180)});
                      },
                      child: Text("点击跳转详情"),
                    ),
                    Selector<AMCommonViewModel, AMCommonViewModel>(
                      selector: (ctx, countVM) => countVM,
                      shouldRebuild: (prev, next) => false,
                      //优化child不重建
                      child: Text("计数器+1"),
                      builder: (ctx, countVM, child) {
                        return MaterialButton(
                          color: Colors.redAccent,
                          textColor: Colors.white,
                          onPressed: () {
                            /// 修改数据
                            setState(() {
                              countVM.count += 1;
                            });
                          },
                          child: child,
                        );
                      },
                    ),
                  ],
                ),
              ),
            ),
            AMCardView01(),
            AMCardView02()
          ],
        ),
      ),
    );
  }
}

class AMCardView01 extends StatelessWidget {
  const AMCardView01({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    ///3.在其他位置共享数据
    var resCount = Provider.of<AMCommonViewModel>(context).count;
    return Container(
      height: 80,
      width: double.infinity,
      child: Card(
        color: Colors.orange,
        child: Column(
          children: [
            Center(
              child: Text("当前的数量为$resCount"),
            )
          ],
        ),
      ),
    );
  }
}

class AMCardView02 extends StatelessWidget {
  ///3.在其他位置共享数据
  const AMCardView02({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var resCount = Provider.of<AMCommonViewModel>(context).count;
    return Container(
      height: 80,
      width: double.infinity,
      child: Card(
        color: Colors.yellow,
        child: Column(
          children: [
            Center(
              child: Text("当前的数量为$resCount"),
            )
          ],
        ),
      ),
    );
  }
}

效果图

版权声明:
作者:Amber
链接:https://late.run/archives/111
来源:LATE-努力努力再努力
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录