一、GetBuilder 手動管理
先看看一個簡單的例子 建立Controller和View類,Controller里面主動調(diào)用update() 去刷新View層里面的UI。
class Controller extends GetxController {
int counter = 0;
void increment() {
counter++;
update(); // 當(dāng)調(diào)用增量時(shí),使用update()來更新用戶界面上的計(jì)數(shù)器變量。
}
}
GetBuilder<Controller>(
init: Controller(),
builder: (_) => Text(
'${_.counter}',
),
1.核心思想

1.1定義一個繼承GetxController的類: 邏輯- Controller 層
1.2定義一個GetBuilder類:界面- *View 層
1.3controlelr 里面調(diào)用update() 刷新UI
2.view,controller 的關(guān)聯(lián)
2.1 分析GetBuilder 的源碼
2.1.1 它是一個StatefulWidget
2.1.2 initState()尋找定義的Controller. 這里有一些尋找策略,跟2.1.3 我們這沒關(guān)系忽略掉subscribeToController() Cool找到了! 準(zhǔn)備開始建立關(guān)系 給Controller通過調(diào)用addListner()的方法增加一個監(jiān)聽者, 并綁定一個函數(shù)getUpdate
2.1.4 getUpdate 來源于GetStateUpdaterMixin 功能很簡單: 當(dāng)前widget存活就執(zhí)行setState()
// get-3.22.2/lib/get_state_manager/src/simple/get_state.dart
class GetBuilder<T extends GetxController> extends StatefulWidget {
final GetControllerBuilder<T> builder;
final T init;
...
@override
_GetBuilderState<T> createState() => _GetBuilderState<T>();
}
class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> with GetStateUpdaterMixin {
T controller;
@override
void initState() {
// 尋找Controller
...
// 訂閱
_subscribeToController();
}
void _subscribeToController() {
remove?.call();
remove = (widget.id == null)
? controller?.addListener(getUpdate)
: controller?.addListenerId(widget.id, getUpdate);
}
}
mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> {
void getUpdate() {
if (mounted) setState(() {});
}
}
2.2分析 GetxController 的源碼
2.2.1GetxController 實(shí)現(xiàn)了Listenable可監(jiān)聽對象的協(xié)議
2.2.2.addListener時(shí)記錄到一個List對象里, 并取名為updater
2.2.3調(diào)用update() -> refresh() 迭代所有監(jiān)聽者并調(diào)用.
class GetxController extends DisposableInterface with ListNotifier {
void update([List<String> ids, bool condition = true]) {
// 移除無用的代碼
...
refresh();
...
}
}
class ListNotifier implements Listenable {
List<GetStateUpdate> _updaters = <GetStateUpdate>[];
@protected
void refresh() {
for (var element in _updaters) {
element();
}
}
@override
Disposer addListener(GetStateUpdate listener) {
_updaters.add(listener);
return () => _updaters.remove(listener);
}
}
2.3.1 GetBuilder是一個狀態(tài)類,它建立了和Controller的關(guān)系并在initState()時(shí)增加當(dāng)前View作為監(jiān)聽者.
2.3.2 Controller里維護(hù)了一個updater的列表記錄每個監(jiān)聽者,在update()的時(shí)候會通知刷新所有View的狀態(tài)。
3.總結(jié)
優(yōu)點(diǎn): API足夠簡單清晰,占用很少內(nèi)存資源。
不足: 還是需要我們?nèi)ナ謩觰pdate(),
二、GetX 響應(yīng)式自動管理
直接上代碼:
class Controller extends GetXcontroller {
final count1 = 0.obs;
final count2 = 0.obs;
int get sum => count1.value + count2.value;
}
GetX<Controller>(
builder: (controller) {
print("count 1 rebuild");
return Text('${controller.count1.value}');
},
),
1.核心思想

1.1 定義一個Controller類: 邏輯 - Controller 層
Controller里包含多個以 .obs 的形式表示的變量,我們把這個變量稱作為響應(yīng)式變量。
1.2 定義一個GetBuilder類:界面 - View 層。
1.3 只要響應(yīng)式變量發(fā)生改變,就會自動通知View刷新界面。
2 分析GetX的源碼
2.1GetX 是一個StatefulWidget
class GetX<T extends DisposableInterface> extends StatefulWidget {
final GetXControllerBuilder<T> builder;
const GetX({
this.builder,
});
@override
GetXState<T> createState() => GetXState<T>();
}
2.2GetState類初始化的時(shí)候創(chuàng)建一個 _observer = RxNotifier() RxNotifier()里包含一個Stream的流.
2.2.1 initState() _observer 開始增加一個監(jiān)聽者刷新View
class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
GetXState() {
_observer = RxNotifier();
}
RxInterface _observer;
StreamSubscription subs;
@override
void initState() {
// 尋找controller
// ...
subs = _observer.listen((data) => setState(() {}));
super.initState();
}
}
2.2.1 build() 這里很有意思. 把_observer作為RxInterface.proxy 的臨時(shí)屬性,在使用builder的后恢復(fù)原有的屬性, 需要注意的是builder(controller)函數(shù)里一定要包含obs.value, 要不然會提示異常。
Widget get notifyChildren {
final observer = RxInterface.proxy;
RxInterface.proxy = _observer;
final result = widget.builder(controller);
if (!_observer.canUpdate) {
throw """
[Get] the improper use of a GetX has been detected.
You should only use GetX or Obx for the specific widget that will be updated.
If you are seeing this error, you probably did not insert any observable variables into GetX/Obx
or insert them outside the scope that GetX considers suitable for an update
(example: GetX => HeavyWidget => variableObservable).
If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.
""";
}
RxInterface.proxy = observer;
return result;
}
@override
Widget build(BuildContext context) => notifyChildren;
2.2.3 執(zhí)行builder(controller) 包含調(diào)用obs.value的屬性. 開始訂閱當(dāng)前屬性的變化, 當(dāng)發(fā)生改變事就自動觸發(fā)setState() 這是GetX的核心的地方;
mixin RxObjectMixin<T> on NotifyManager<T> {
// controller.count.value
T get value {
if (RxInterface.proxy != null) {
RxInterface.proxy.addListener(subject);
}
return _value;
}
}
mixin NotifyManager<T> {
GetStream<T> subject = GetStream<T>();
final _subscriptions = <StreamSubscription>[];
void addListener(GetStream<T> rxGetx) {
if (_subscriptions.contains(rxGetx.listen)) {
return;
}
final subs = rxGetx.listen((data) {
subject.add(data);
});
_subscriptions.add(subs);
}
}
3 總結(jié)
GetX 初始化的時(shí)候會創(chuàng)建一個Stream,它來監(jiān)聽當(dāng)前View的變化,當(dāng)UI中響加載 obs.value 時(shí),就會把 View刷新 掛載到這個obs屬性上。 只要屬性變化就會通知View刷新頁面。