簡單狀態管理器
GetxController
有一個 update 方法,用於觸發更新操作。
類似於 ChangeNotifier 中的 notifyListeners 方法
源碼
abstract class GetxController extends DisposableInterface with ListenableMixin, ListNotifierMixin { void update([List<Object>? ids, bool condition = true]) { if (!condition) { return; } if (ids == null) { refresh(); } else { for (final id in ids) { refreshGroup(id); } } } } @protected void refresh() { assert(_debugAssertNotDisposed()); /// This debounce the call to update. /// It prevent errors and duplicates builds // if (_microtask == _version) { // _microtask++; // scheduleMicrotask(() { // _version++; // _microtask = _version; _notifyUpdate(); // }); // } } // 從 _updaters 取出所有的回調函數,一一執行 void _notifyUpdate() { for (var element in _updaters!) { element!(); } }
GetBuilder
初始化的時候,會向 Controller 添加回調函數(訂閱),這個回調函數的作用就是 setState 更新當前 GetBuilder 組件。
部分源碼
class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> with GetStateUpdaterMixin { T? controller; @override void initState() { super.initState(); controller = widget.init; _subscribeToController(); } // 向 controller 添加當前 GetBuilder 的一個回調 void _subscribeToController() { _remove?.call(); _remove = (widget.id == null) ? controller?.addListener( _filter != null ? _filterUpdate : getUpdate, ) : controller?.addListenerId( widget.id, _filter != null ? _filterUpdate : getUpdate, ); } ... } mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> { void getUpdate() { if (mounted) setState(() {}); } }
添加訂閱的方法是在 GetxController 中,即向綁定的 controller 的 _updaters 列表中添加當前 GetBuilder 的回調,以便 controller 執行 update() 方法時,通過此回調更新當前 GetBuilder
相關源碼
@override Disposer addListener(GetStateUpdate listener) { assert(_debugAssertNotDisposed()); _updaters!.add(listener); return () => _updaters!.remove(listener); }
使用示例:
代碼
class Controller extends GetxController { int counter = 0; void increment() { counter++; update(); // 當調用增量時,使用update()來更新用戶界面上的計數器變量。 } } // 在你的Stateless/Stateful類中,當調用increment時,使用GetBuilder來更新Text。 GetBuilder<Controller>( init: Controller(), // 首次啟動 builder: (_) => Text( '${_.counter}', ), )
在 GetBuilder 之外可以通過 Get.find() 獲取,但是無法在值變化時自動更新當前組件
class Controller extends GetxController { /// 你不需要這個,我推薦使用它只是為了方便語法。 /// 用靜態方法:Controller.to.increment()。 /// 沒有靜態方法的情況下:Get.find<Controller>().increment(); /// 使用這兩種語法在性能上沒有區別,也沒有任何副作用。一個不需要類型,另一個IDE會自動完成。 static Controller get to => Get.find(); // 添加這一行 int counter = 0; void increment() { counter++; update(); } } FloatingActionButton( onPressed: () { Controller.to.increment(), } child: Text("${Controller.to.counter}"), ),
注:通過 Get.find() 獲取,並且需要監聽值更新,可以使用 Obx
Obx(() => Text("${controller.name}"));
使用技巧
為 GetBuilder 定義 id,controller 中可以根據 id 進行更新
GetBuilder<Controller>( id: 'text', //這里 init: Controller(), // 每個控制器只用一次 builder: (_) => Text( '${Get.find<Controller>().counter}', //here ), ), update(['text']); // 還可以設置另外的條件 update(['text'], counter < 10);
響應的狀態管理器
區別:不需要在 controller 中執行 update() 方法,相關組件也會自動更新
將變量或對象變成可觀察的 observable
示例:
final name = ''.obs; final isLogged = false.obs; final count = 0.obs; final balance = 0.0.obs; final number = 0.obs; final items = <String>[].obs; final myMap = <String, int>{}.obs; // 自定義類 - 可以是任何類 final user = User().obs;
使用 Getx 監聽相關變量 observer
示例:
// 視圖 GetX<Controller>( builder: (controller) { print("count 1 rebuild"); return Text('${controller.count1.value}'); }, ),
更新 observable 變量
可以直接更新,也可以調用 obs變量的 update 方法進行局部更新
示例:
// 使用 value 去更新 controller.count.value++ // model // 我們將使整個類成為可觀察的,而不是每個屬性。 class User{ User({this.name = '', this.age = 0}); String name; int age; } // controller final user = User().obs; //當你需要更新user變量時。 user.update( (user) { // 這個參數是你要更新的類本身。 user.name = 'Jonny'; user.age = 18; }); // 更新user變量的另一種方式。 user(User(name: 'João', age: 35)); // view // 可以不使用.value來訪問模型值。 user().name;
2333