flutter —— 使用 getx 進行狀態管理


簡單狀態管理器

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變量名> .firstRebuild = false;

 

更新 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM