Flutter ValueNotifier 异步通信、ValueListenableBuilder异步更新数据

来源:blog.csdn.net 更新时间:2023-05-25 21:55
本文章讲述使用 Navigator 更新页面 A 的数据、ValueListenableBuilder 的基本使用、自定义 ValueNotifier 进行局部数据的更新

1 前言
在实际项目开发中,有一种业务需求就是 页面A 进入页面B ,在页面B中数据发生改变后需要更新页面A 中的内容,其实第一种方案可以考虑使用 then函数回调,如下代码清单1-1所示,在页面A中以动态路由的方式打开页面TestBPage,并实现 Navigator 的then 函数,then 函数会在 TestBPage 页面关闭时回调。

///代码清单 1-1 
 void openPageFunction(BuildContext context) {
   ///以动态路由的方式打开
   Navigator.of(context).push(
     MaterialPageRoute(
       builder: (BuildContext context) {
         return TestBPage();
       },
     ),
     ///页面 TestBPage 关闭后会回调 then 函数
     ///其中参数 value 为回传的参数
   ).then((value) {
     if (value != null) {
       setState(() {
         _message = value;
       });
     }
   });
 }

当在页面 TestBPage 关闭时,可以主动回传参数,如下代码 清单 1-2 所示:

 ///代码 清单 1-2
 OutlineButton buildOutlineButton(BuildContext context) {
   return OutlineButton(
     child: Text("返回页面 A "),
     onPressed: () {
       String result = "345";
       Navigator.of(context).pop(result);
     },
   );
 }

这一种方法的一个实际应用场所如一个订单的详情页面,打开下一个页面进行操作后,再返回当前页面后需要刷新页面的数据,此种场景就可使用这种方法。

使用 then 函数达成的数据传递或者说页面刷新,对于用户来讲是可见的,就是有时数据刷新的慢点,用户是可以有感觉的,使用ValueNotifier可以达到无感刷新。

2 ValueNotifier 的基本使用
ValueNotifier 需要结合组件 ValueListenableBuilder 来使用。

/// 第一步 定义 ValueNotifier  这里传递的数据类型为 String
ValueNotifier<String> _testValueNotifier = ValueNotifier<String>('');

///第二步定义 数据变化后监听的 Widget
Widget buildValueListenableBuilder() {
  return ValueListenableBuilder(
    ///数据发生变化时回调
    builder: (context, value, child) {
      return Text(value);
    },
    ///监听的数据
    valueListenable: _testValueNotifier,
    child: Text(
      '未登录',
      style: TextStyle(color: Colors.red),
    ),
  );
}

///第三步就是数据变化后
 void testFunction() {
   ///赋值更新
   _testValueNotifier.value = '传递的测试数据';
 }

在上述代码片段中,传递更新的数据是一个String,当然在业务开发场景中,会有更多自定义的 Model,直接替换上述的String就可以。

3 自定义 ValueNotifier 局部更新
如有一个用户数据类型的Model定义如下 :

///实际中变量可能足够的多
class UserInfo {
  String name;
  int age ;
}

我们期望只修改其中的如 age 一个属性的值,此时就需要自定 ValueNotifier ,如下代码清单 1-3 所示:

///代码清单 1-3 
///自定义 ValueNotifier
/// UserInfo 为数据类型
class UserNotifier extends ValueNotifier<UserInfo> {

  UserNotifier(UserInfo userInfo): super(userInfo);

  void setName(String name) {
    ///赋值 这里需要注意的是 如果没有给 ValueNotifier 赋值 UserInfo 对象时
    /// value 会出现空指针异常
    value.name =name;
    ///通知更新
    notifyListeners();
  }

}

然后在使用的时候,创建 UserNotifier 如下 :

///第一步
UserNotifier _testUserNotifier = UserNotifier(UserInfo(name: "", age: 0));

构建 ValueListenableBuilder

 ///第二步 定义
 Widget buildUserListenableBuilder() {
   return ValueListenableBuilder(
     ///数据发生变化时回调
     builder: (context, value, child) {
       return Text("姓名是:${value.name}  年龄是: ${value.age}");
     },
     ///监听的数据
     valueListenable: _testUserNotifier,
   );
 }


当数据变化时进行更新操作

 void testUserFunction() {
   _testUserNotifier.setName("李四");
 }

这种应用场景如实际项目开发中的修改用户数据,只修改了其中的一个属性数据,可以考虑使用这种方法,当然有很多情况大家是不考虑这种细节的,直接全部更新的,但是所有的细节综合起来,就解决了 你的应用为什么体验总是差点的问题。