Flutter Provider Selector数据更新问题优化
在使用
Selector
的时候,在修改所选对象里面的某个参数之后调用notifyListeners()
,界面并不会更新,再比如选择的是个数组,对数组进行操作之后,调用notifyListeners()
也是不会更新,造成这个问题的主要原因是由于对象内存地址并没有改变导致的,当内存地址没有改变,就不会更新。
我们为了解决这个问题,一般是重新创建一个对象, 然后把原来的值重新赋值到新的对象上,比如数组:
List<String> newList=[];
newList.addAll(list);
newList.add("test");
list=newList;
notifyListeners();
当这个数组是个对象数组的时候,我们需要修改数组里面的对象里面的某个参数的时候,不仅数组需要重建,里面的对象也需要重建,比如:
List<User> newList = [];
newList.addAll(list);
newList[index] = User()
..name = "test1"
..age=list[index].age
..gender=list[index].gender;
list = newList;
notifyListeners();
这虽然能够解决问题,但是非常麻烦,并且效率不高。
优化
查看Selector
的属性可以发现有个shouldRebuild
这个属性,里面有两个值,一个是收到更新通知之后新的数据,一个还是缓存的数据,通过判断这两个值来决定是否刷新,默认preview!=next
就刷新,我们可以通过这个属性来做一些处理进行优化。
我们只需要加上version
,通过它来判断数据是否有更新便可以了
bool shouldRebuild() {
bool isUpdate = _version != _lastVersion;
if (isUpdate) {
_lastVersion = _version;
}
return isUpdate;
}
我们对其进行一下封装,首先定义一个类来进行承载数据,传入的泛型就会Selector
中用到的数据类型
class SelectorPlusData<T> {
T? _value;
int _version = 0;
int _lastVersion = -1;
T? get value => _value;
SelectorPlusData({Key? key, T? value}) {
_value = value;
}
set value(T? value) {
_version++;
_value = value;
}
bool shouldRebuild() {
bool isUpdate = _version != _lastVersion;
if (isUpdate) {
_lastVersion = _version;
}
return isUpdate;
}
}
接着对Selector
也进行一下处理
class SelectorPlus<A, T> extends Selector<A, SelectorPlusData<T?>> {
SelectorPlus({
Key? key,
required ValueWidgetBuilder<T?> builder,
required SelectorPlusData<T?> selector,
ShouldRebuild<SelectorPlusData>? shouldRebuild,
Widget? child,
}) : super(
key: key,
builder: (context, value, child) =>
builder(context, value.value, child),
selector: (context, value) => selector,
shouldRebuild: (previous, next) => next.shouldRebuild(),
child: child,
);
}
使用
比如我们需要监听的对象是UserModel
SelectorPlus<UserController, UserModel>(
selector: controller.data,
builder: (context, value, child) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"name: ${value?.name}",
),
Text(
"email: ${value?.email}",
),
],
),
);
},
)
修改数据,然后刷新UI
data.value?.name = 'Flutter';
data.update();
notifyListeners();
或者
data.value = UserModel(name: "Flutter", email: "123@xx.com");
notifyListeners();
当然,对数组类数据也进一步做了处理,具体使用如下:
SelectorListPlus<UserController, UserModel>(
selector: controller.list,
builder: (context, value, child) {
return ListView.builder(
itemCount: value.length,
itemBuilder: (context, index) {
final item = value[index];
return ListTile(
title: Text(item.name),
subtitle: Text(item.email),
);
},
);
},
)
修改数据更新UI
list.value[index].name = 'Flutter';
list.update();
notifyListeners();
或者
list.value= [UserModel(name: "Flutter", email: "123@xxx.com")];
notifyListeners();
增加
list.add(UserModel(name: "Flutter", email: "123@xx.com"));
notifyListeners();
删除
list.remove(index);
notifyListeners();
最后
GitHub地址:selector_plus
转载自:https://juejin.cn/post/7095915949961773069