flutter开发实战-ValueListenableBuilder实现局部刷新功能

flutter开发实战-ValueListenableBuilder实现局部刷新功能

在创建的新工程中,点击按钮更新counter后,通过setState可以出发本类的build方法进行更新。当我们只需要更新一小部分控件的时候,通过setState就不太合适了,这就需要进行局部更新,可以通过provider等状态管理库来实现。当然flutter为我们提供了ValueListenableBuilder来实现局部控件的刷新。

一、ValueListenableBuilder

ValueListenableBuilder的属性如下

const ValueListenableBuilder({
    super.key,
    required this.valueListenable,
    required this.builder,
    this.child,
  }) : assert(valueListenable != null),
       assert(builder != null);
    
  • ValueListenable继承自Listenable,是一个可监听对象。
  • builder是一个typedef
    typedef ValueWidgetBuilder = Widget Function(BuildContext context, T value, Widget? child);
  • child,可选,可为空

查看ValueListenableBuilder类的实现可以看到

class _ValueListenableBuilderState<T> extends State<ValueListenableBuilder<T>> {
  late T value;

  @override
  void initState() {
    super.initState();
    value = widget.valueListenable.value;
    widget.valueListenable.addListener(_valueChanged);
  }

  @override
  void didUpdateWidget(ValueListenableBuilder<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.valueListenable != widget.valueListenable) {
      oldWidget.valueListenable.removeListener(_valueChanged);
      value = widget.valueListenable.value;
      widget.valueListenable.addListener(_valueChanged);
    }
  }

  @override
  void dispose() {
    widget.valueListenable.removeListener(_valueChanged);
    super.dispose();
  }

  void _valueChanged() {
    setState(() { value = widget.valueListenable.value; });
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(context, value, widget.child);
  }
}
    

在initState中对传入的可监听对象进行监听,执行_valueChanged方法,_valueChanged执行了setState来触发当前状态的刷新。我们知道setState会执行build方法,触发执行build方法,最总触发widget.builder回调,这样就实现了局部刷新。

child的作用也是非常重要的,我们将Widget放到child中,在执行builder时,会直接使用child,将不会再构建一遍child。

二、ValueListenableBuilder实现局部刷新示例

下面使用ValueListenableBuilder来实现一个局部刷新的示例。示例中,在界面中,有一个显示按钮与隐藏按钮控制修改isShowNotifier的value。通过ValueListenableBuilder的builder中来判断需要显示的内容。
示例代码如下

import 'package:flutter/material.dart';

class ValueListenablePage extends StatefulWidget {
  const ValueListenablePage({super.key});

  @override
  State<ValueListenablePage> createState() => _ValueListenablePageState();
}

class _ValueListenablePageState extends State<ValueListenablePage> {
  final isShowNotifier = ValueNotifier<bool>(false);

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  void show() {
    isShowNotifier.value = true;
  }

  void hide() {
    isShowNotifier.value = false;
  }

  @override
  void dispose() {
    // TODO: implement dispose
    isShowNotifier.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    return Scaffold(
      appBar: AppBar(
        title: const Text('ValueListenablePage'),
      ),
      body: Container(
        width: screenSize.width,
        height: screenSize.height,
        child: Stack(
          alignment: Alignment.center,
          children: [
            Positioned(
              top: 50,
              child: buildValueListenable(context),
            ),
            Positioned(
              top: 200,
              child: buildButton(context),
            ),
          ],
        ),
      ),
    );
  }

  Widget buildHide(BuildContext context) {
    return Container(
      color: Colors.green,
      padding: EdgeInsets.symmetric(vertical: 20, horizontal: 50),
      child: Text(
        "当前隐藏",
        textAlign: TextAlign.center,
        overflow: TextOverflow.ellipsis,
        softWrap: true,
        style: TextStyle(
          fontSize: 16,
          fontWeight: FontWeight.w600,
          fontStyle: FontStyle.italic,
          color: Colors.white,
          decoration: TextDecoration.none,
        ),
      ),
    );
  }

  Widget buildValueListenable(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: isShowNotifier,
      builder: (BuildContext aContext, bool isShow, Widget? child) {
        if (isShow) {
          return child ?? buildHide(context);
        } else {
          return buildHide(context);
        }
      },
      child: Container(
        color: Colors.blueGrey,
        padding: EdgeInsets.symmetric(vertical: 50, horizontal: 50),
        child: Text(
          "ValueListenableBuilder Child",
          textAlign: TextAlign.center,
          overflow: TextOverflow.ellipsis,
          softWrap: true,
          style: TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.w600,
            fontStyle: FontStyle.italic,
            color: Colors.white,
            decoration: TextDecoration.none,
          ),
        ),
      ),
    );
  }

  Widget buildButton(BuildContext context) {
    return Container(
      width: 300,
      height: 220,
      color: Colors.deepOrange,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          TextButton(
            onPressed: () {
              show();
            },
            child: Container(
              height: 50,
              width: 200,
              color: Colors.lightBlue,
              alignment: Alignment.center,
              child: Text(
                '点击显示',
                style: TextStyle(
                  fontSize: 14,
                  color: Colors.white,
                ),
              ),
            ),
          ),
          TextButton(
            onPressed: () {
              hide();
            },
            child: Container(
              height: 50,
              width: 200,
              color: Colors.lightBlue,
              alignment: Alignment.center,
              child: Text(
                '点击隐藏',
                style: TextStyle(
                  fontSize: 14,
                  color: Colors.white,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

    

效果图如下

在这里插入图片描述

在这里插入图片描述

三、小结

flutter开发实战-ValueListenableBuilder实现局部刷新功能

学习记录,每天不停进步。

猜你喜欢

转载自blog.csdn.net/gloryFlow/article/details/134732970