背景:
实现最小颗粒化的刷新,减少没必要的 rebuild
业务使用场景:
- 首先来看看正常的GetBuilder的构造方法
GetBuilder<T extends GetxController>(builder: (logic) {
});
说明:
GetxController实现类,只要调用了update(), 那么所有的GetBuilder关联的GetxController类都会被刷新到,但有的时候,我们只是需要刷新关联数据的,所以这个就需要缓存widget只在满足条件下的时候才刷新widget
- 添加条件判断代码
/// 改造伪代码
GetBuilder<T extends GetxController>(builder: (logic) {
return Container();
}, shouldRebuild: (GetxController oldCtl, GetxController newCtl) {
/// 如果新的GetxController 不等于老的GetxController 那就执行更新操作。
return newCtl != oldCtl;
});
ps: 有了上面的业务背景,和条件判断的伪代码,那我们就可以编写真正的代码了
封装实现:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
/// 构建一个是否刷新的判断条件函数
typedef GetShouldRebuildFunction<T> = bool Function(T oldController, T newController);
/// 是否需要rebuild
class GetShouldRebuild<T extends GetxController> extends StatefulWidget {
/// 沿用GetBuilder的builder 构建widget
final GetControllerBuilder<T> builder;
final GetShouldRebuildFunction<T>? shouldRebuild;
const GetShouldRebuild({Key? key, required this.builder, this.shouldRebuild}) : super(key: key);
@override
_GetShouldRebuildState<T> createState() => _GetShouldRebuildState<T>();
}
class _GetShouldRebuildState<T extends GetxController> extends State<GetShouldRebuild<T>> {
/// 缓存的widget
Widget? oldWidget;
/// 记录刷新之后的Controller
T? oldController;
@override
Widget build(BuildContext context) {
return GetBuilder<T>(builder: (T newController) {
/// 1. 没有缓存的widget,就创建一个
/// 2. 没有使用调用shouldRebuild,就每次都调用builder
/// 3. 根据shouldRebuild 返回的条件决定是否调用builder更新widget,否则使用缓存的widget
if (oldWidget == null ||
(widget.shouldRebuild == null ? true : widget.shouldRebuild!(oldController!, newController))) {
final T controller = newController;
final Widget newWidget = widget.builder(newController);
oldController = controller;
oldWidget = newWidget;
}
return oldWidget!;
});
}
}
业务落实使用:
真正的关联条件代码,跟
GetBuilder一样的构建方式,只不过多了一个shouldRebuild
GetShouldRebuild<TenlantsGrowthLogic>(builder: (newCtl) {
/// 根据新的 GetxController 来构建widget
return Container();
}, shouldRebuild: (oldCtl, newCtl) {
/// 判断新老 GetxController 是否相同
return oldCtl != newCtl;
});