Flutter中的局部刷新-ValueNotifier和ValueListenableBuilder

一、前言

在Flutter中通常刷新UI是使用setState(() {});进行刷新,只是这种方式会让UI进行全局刷新,对于比较复杂的页面来说,如果仅仅是改变其中一小部分的UI来说进行刷新是不恰当的,因此官方提供了ValueNotifier来进行刷新。ValueNotifier是一个泛型,所以可以传递各种数据。ValueNotifier不仅仅可以进行单个组件的刷新,也可以同时被多个组件进行监听,还可以对自定义数据进行处理,本文通过一个点击按钮改变数字的功能进行演示。ValueNotifier其父类为ChangeNotifier,可以参考以下链接进行了解:
https://blog.csdn.net/Mr_Tony/article/details/112345491

二、单个数据的刷新

void main() => runApp(MyApp());

ValueNotifier<int> _valueNotifier = ValueNotifier<int>(0);//数据监听器

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Material App Bar'),
        ),
        body: Center(
          child: Container(
            child: Column(
              children: [
                ChildWidget1(),
                ChildWidget2()
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class ChildWidget1 extends StatefulWidget {
  @override
  _ChildWidget1State createState() => _ChildWidget1State();
}

class _ChildWidget1State extends State<ChildWidget1> {
  @override
  Widget build(BuildContext context) {
    print('YM---ChildWidget1----进行刷新啊');
    return ValueListenableBuilder<int>(
      valueListenable: _valueNotifier,
      builder: (BuildContext context, int value, Widget child){
        print('YM----ChildWidget1-----ValueListenableBuilder----进行刷新啊');
        return Text('ChildWidget1新值:$value');
      },
      // child: Container(
      //   child: Text('子控件'),
      // ),
    );
  }
}

class ChildWidget2 extends StatefulWidget {
  @override
  _ChildWidget2State createState() => _ChildWidget2State();
}

class _ChildWidget2State extends State<ChildWidget2> {
  @override
  Widget build(BuildContext context) {
    print('YM---ChildWidget2----进行刷新啊');
    return Container(
      child: RaisedButton(
        onPressed: (){
          _valueNotifier.value++;
        },
        child: Text('点击更改其它地方的数据'),
      ),
    );
  }
}

三、多个数据的监听

class ChildWidget3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<int>(
      valueListenable: _valueNotifier,
      builder: (BuildContext context, int value, Widget child){
        print('YM--ChildWidget3-----ValueListenableBuilder----进行刷新啊');
        return Text('ChildWidget3新值:$value');
      },
      // child: Container(
      //   child: Text('子控件'),
      // ),
    );
  }
}

...
    Column(
              children: [
                ChildWidget1(),
                ChildWidget2(),
                ChildWidget3()
              ],
            )
...

四、自定义数据的监听

在实际业务中,通常会定义数据模型,对于单个实例也只是改变里面的数据,因此需要用到自定义ValueNotifier的方式,通过将上文的int值包装在一个实体类里面来对该功能进行演示

自定义的CounterValueNotifier如下:

class Counter{
  int count = 0;
}

class CounterValueNotifier extends ValueNotifier<Counter>{

  CounterValueNotifier(Counter counter):super(counter);

  changeCount(){
    value.count++;
    notifyListeners();
  }
}

CounterValueNotifier _counterValueNotifier = CounterValueNotifier(Counter());

修改ValueListenableBuilder如下:

ValueListenableBuilder<Counter>(
      valueListenable: _counterValueNotifier,
      builder: (BuildContext context, Counter value, Widget child){
        print('YM----ChildWidget1-----ValueListenableBuilder----进行刷新啊');
        return Text('ChildWidget1新值:${value.count}');
      },
      // child: Container(
      //   child: Text('子控件'),
      // ),
    )

修改点击事件如下:

RaisedButton(
  onPressed: (){
   _counterValueNotifier.changeCount();
  },
  child: Text('点击更改其它地方的数据'),
)

五、参考链接

  1. Flutter 组件 | ValueListenableBuilder 局部刷新小能手:

    https://juejin.cn/post/6912206134078078990

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

    https://blog.csdn.net/zl18603543572/article/details/109151309

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值