在getx状态管理(一)中使用0.obs Obx(()=>Text(""))实现UI自动响应数据的变化,
现在来看第二种实现方式数据监听.
GetBuilder + update手动更新
class TestController extends GetxController {
int count = 0;
increment() {
count++;
update();
}
}
class TestWidget extends GetView<TestController> {
@override
Widget build(BuildContext context) {
return GetBuilder<TestController>(
builder: (controller) => Text("${controller.count}"));
}
}
GetBuilder 添加监听 刷新页面
@override
void initState() {
super.initState();
//controller 注册
...
//添加监听
_subscribeToController();
}
void _subscribeToController() {
//如果存在,先移除
_remove?.call();
_remove = (widget.id == null)
? controller?.addListener(
_filter != null ? _filterUpdate : getUpdate,
)
: controller?.addListenerId(
widget.id,
_filter != null ? _filterUpdate : getUpdate,
);
}
@override
void dispose() {
super.dispose();
widget.dispose?.call(this);
if (_isCreator! || widget.assignId) {
if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) {
GetInstance().delete<T>(tag: widget.tag);
}
}
_remove?.call();
controller = null;
_isCreator = null;
_remove = null;
_filter = null;
}
//刷新页面
mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> {
//如果element存在,调用 setState((){})刷新页面
void getUpdate() {
if (mounted) setState(() {});
}
}
controller.update() 更新数据
GetxController
abstract class GetxController extends DisposableInterface with ListenableMixin, ListNotifierMixin
//ids 更新有id的widget, condition 更新条件
void update([List<Object>? ids, bool condition = true]) {
if (!condition) {
return;
}
if (ids == null) {
refresh();
} else {
for (final id in ids) {
refreshGroup(id);
}
}
}
}
GetxController with ListNotifierMixin
1. addListener 添加监听到_updaters中并返回一个移除监听的Function
2. refresh 执行_updaters中的方法
3. 执行getUpdate setState()执行build()
4. removeListener 移除监听
mixin ListNotifierMixin on ListenableMixin {
//监听列表
List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[];
HashMap<Object?, List<GetStateUpdate>>? _updatersGroupIds =
HashMap<Object?, List<GetStateUpdate>>();
///1.
@protected
void refresh() {
_notifyUpdate();
}
//2.刷新所有添加监听的widget
void _notifyUpdate() {
for (var element in _updaters!) {
element!();
}
}
//3.刷新特定id的widget
void _notifyIdUpdate(Object id) {
if (_updatersGroupIds!.containsKey(id)) {
final listGroup = _updatersGroupIds![id]!;
for (var item in listGroup) {
item();
}
}
}
@protected
void refreshGroup(Object id) {
_notifyIdUpdate(id);
}
@protected
void notifyChildrens() {
TaskManager.instance.notify(_updaters);
}
bool get hasListeners {
assert(_debugAssertNotDisposed());
return _updaters!.isNotEmpty;
}
int get listeners {
assert(_debugAssertNotDisposed());
return _updaters!.length;
}
//移除监听
@override
void removeListener(VoidCallback listener) {
assert(_debugAssertNotDisposed());
_updaters!.remove(listener);
}
void removeListenerId(Object id, VoidCallback listener) {
assert(_debugAssertNotDisposed());
if (_updatersGroupIds!.containsKey(id)) {
_updatersGroupIds![id]!.remove(listener);
}
_updaters!.remove(listener);
}
@mustCallSuper
void dispose() {
assert(_debugAssertNotDisposed());
_updaters = null;
_updatersGroupIds = null;
}
/// GetBuild 添加监听
// 返回一个移除监听的Function
@override
Disposer addListener(GetStateUpdate listener) {
assert(_debugAssertNotDisposed());
_updaters!.add(listener);
return () => _updaters!.remove(listener);
}
Disposer addListenerId(Object? key, GetStateUpdate listener) {
_updatersGroupIds![key] ??= <GetStateUpdate>[];
_updatersGroupIds![key]!.add(listener);
return () => _updatersGroupIds![key]!.remove(listener);
}
/// To dispose an [id] from future updates(), this ids are registered
/// by `GetBuilder()` or similar, so is a way to unlink the state change with
/// the Widget from the Controller.
void disposeId(Object id) {
_updatersGroupIds!.remove(id);
}
}