Flutter 局部刷新小组件汇总

前言:
在Flutter实际的开发工作中,局部刷新也就是更小的颗粒度刷新一直是开发者追求的一个目标,总结一下几个常用的局部刷新的小组件。
首先来说有很多状态管理的框架,可以轻松实现局部刷新。
  1. Provider :使用 Consumer 或者 Selector 来实现。

  2. Bloc :使用 BuildWhen 来实现。

  3. GetX :使用 Obx() 来实现。

  4. RiverPod通过 ref.watch(homeDetailScrollRiverProvider.select 或者 细化拆分river 来实现。

其实,Flutter本身自己也提供了局部刷新的小组件,随着业务的复杂,用这些小组件配合状态管理框架一起来使用,会使颗粒度更细,法力无边。
一. StatefulWidget

在写页面时,尽量的细化和封装组件,小组件继承 StatefulWidget 通过 setStates 来更新小组件自己,页面上其他组件不变。

二. StatefulBuilder

有些时候可能一个小组件或者页面相对复杂,而需要根据状态变化的 Widget 只有一个,要想做到更小颗粒度的刷新那肯定就不能调用 setStates ,因为小组件本身不需要全部重新 build 只是需要重新构建根据状态变化的 Widget 即可。

简单来说,StatefulBuilder 是一个 "便携式"、"嵌入式"的 StatefulWidget , 它的独特之处在于它的 builder 方法,这个方法提供了一个 setState 回调,你可以用这个回调来触发仅重建 StatefulBuilder 内部 UI 的局部刷新。

在实际的项目开发过程中有很多使用的场景,比如 表单选择 点赞 收藏 等 。

写了一个例子,点击 widget 改变自身文字显示 代码如下:

dart 复制代码
return StatefulBuilder(
  builder: (context, buildSetState) {
    return InkWell(
      onTap: () {
        _title = Until.getTitle();
        buildSetState.call(() {});
      },
      child: Container(
        width: double.infinity,
        color: Colors.white,
        alignment: Alignment.center,
        padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 18.w),
        child: Text(_title),
      ),
    );
  },
);
三. ValueNotifier + ValueListenableBuilder

ValueListenableBuilder 的使用场景和 StatefulBuilder 类似,二者在很多的场景中可以互相替代。

ValueListenableBuilder官方推荐 的用于中等复杂度场景的局部刷新方案。它将数据(ValueNotifier)UI(ValueListenableBuilder) 分离,实现完美解耦。

极致的局部刷新ValueListenableBuilderbuilder 方法就是需要刷新的最小范围。

完美解耦 :组件之间不需要互相知道对方的存在,它们只通过 ValueNotifier通信。

写了一个例子,点击 widget 改变自身文字显示 代码如下:

dart 复制代码
Widget _valueNotifierWidget() {
  return ValueListenableBuilder<String>(
    valueListenable: _valueNotifier,
    builder: (context, value, child) {
      return InkWell(
        onTap: () {
          _valueNotifier.value = Until.getTitle();
        },
        child: Container(
          width: double.infinity,
          color: Colors.white,
          alignment: Alignment.center,
          margin: EdgeInsets.symmetric(vertical: 12.h),
          padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 18.w),
          child: Text(value),
        ),
      );
    },
  );
}
三. StreamBuilder

对于异步数据流(比如来自网络、文件读取),用 StreamBuilder 来实现局部刷新也有助于解耦。

写了一个例子,网络请求数据,成功之后更新自身文字展示 代码如下:

dart 复制代码
Widget _streamBuilderWidget() {
  return StreamBuilder<CarModel?>(
    stream: _carStream,
    builder: (context, snapshot) {
      if (snapshot.hasError) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.error_outline, color: Colors.red, size: 60),
            const SizedBox(height: 16),
            Text(
              '出错啦: ${snapshot.error}',
              style: Theme.of(context).textTheme.bodyLarge,
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 16),
            FilledButton(
              onPressed: _refreshData, // 出错后可以重试
              child: const Text('重试'),
            ),
          ],
        );
      } else if (snapshot.hasData) {
        return Container(
          color: Colors.blue,
          padding: const EdgeInsets.all(8.0),
          child: Text(snapshot.data?.description ?? ""),
        );
      } else {
        return const CircularProgressIndicator();
      }
    },
  );
}
四. FutureBuilder

FutureBuilder 是 Flutter 中用于处理单次异步操作 并据此构建 UI 的强大组件。它比 StreamBuilder 更简单,适用于绝大多数"请求-响应"模式的场景,如网络请求、数据库查询、本地文件读取等。

写了一个例子,网络请求数据,成功之后更新自身文字展示 代码如下:

dart 复制代码
Widget _futureBuilderWidget() {
  return FutureBuilder<CarModel?>(
    future: _futureCar,
    builder: (context, snapshot) {
      if (snapshot.hasError) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.error_outline, color: Colors.red, size: 60),
            const SizedBox(height: 16),
            Text(
              '出错啦: ${snapshot.error}',
              style: Theme.of(context).textTheme.bodyLarge,
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 16),
            FilledButton(
              onPressed: _refreshStream, // 出错后可以重试
              child: const Text('重试'),
            ),
          ],
        );
      }
      if (snapshot.hasData) {
        final CarModel? carModel = snapshot.data;
        return Container(
          color: Colors.red,
          padding: const EdgeInsets.all(8.0),
          child: Text(carModel?.description ?? ''),
        );
      }
      return const CircularProgressIndicator();
    },
  );
}

Demo 地址

相关推荐
一只大侠的侠3 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
renke33646 小时前
Flutter for OpenHarmony:色彩捕手——基于HSL色轮与感知色差的交互式色觉训练系统
flutter
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端