使用 GetX 進(jìn)行 Flutter 狀態(tài)管理

言鼎科技 2023-06-19 535

介紹

每當(dāng)我們?cè)?flutter 中開(kāi)始構(gòu)建任何應(yīng)用程序時(shí),我們都必須決定我們需要使用哪種狀態(tài)管理。通過(guò)此博客,您可以更輕松地做出此決定。在這里,在這篇教程:Flutter state management using GetX 中,我想解釋一下 GetX 這個(gè)強(qiáng)大的 flutter 框架。

什么是GetX?

狀態(tài)管理允許您在應(yīng)用程序內(nèi)傳輸數(shù)據(jù)。每當(dāng)傳遞數(shù)據(jù)時(shí),應(yīng)用程序的狀態(tài)都會(huì)更新,從而重建系統(tǒng)。因此,開(kāi)發(fā)人員必須特別小心地管理應(yīng)用程序的狀態(tài),因?yàn)閷?duì)于復(fù)雜的應(yīng)用程序來(lái)說(shuō),狀態(tài)更新有時(shí)看起來(lái)成本很高。

Flutter 傳統(tǒng)上提供 Stateful Widget 來(lái)管理應(yīng)用程序中的狀態(tài)。但是,我們?cè)谑褂糜袪顟B(tài)小部件時(shí)需要處理一些限制。

為了克服這些限制,我們可以選擇使用 GetX 進(jìn)行 Flutter 狀態(tài)管理。

GetX 是 Flutter 提供的用于管理狀態(tài)及其更新的強(qiáng)大且輕量級(jí)的解決方案。它提供:

  • 高性能狀態(tài)管理

  • 智能依賴(lài)注入

  • 快速實(shí)用的路線管理

為什么選擇 GetX?

那么,讓我們更深入地探討一下為什么我們需要 GetX 來(lái)管理 Flutter 應(yīng)用程序中的狀態(tài)。GetX 在三個(gè)不同的標(biāo)準(zhǔn)上改進(jìn)了 flutter 應(yīng)用程序:

  • 生產(chǎn)力:開(kāi)發(fā)人員可以借助簡(jiǎn)單的語(yǔ)法輕松實(shí)現(xiàn) getx 狀態(tài)管理 flutter。無(wú)論代碼片段多么復(fù)雜,您都可以使用 GetX flutter 節(jié)省時(shí)間。它通過(guò)減少提供最佳性能的開(kāi)發(fā)時(shí)間來(lái)提高生產(chǎn)率。

  • 組織和可讀性:GetX 解耦視圖。它提供了簡(jiǎn)單且不復(fù)雜的語(yǔ)法,從而提高了業(yè)務(wù)邏輯的可讀性和格式。

  • 性能:如上所述,GetX 專(zhuān)注于如何消耗最少的資源,這有助于提高應(yīng)用程序性能。它不使用 ChangeNotifier 或 Streams。查看下面描述各種狀態(tài)管理器的 RAM 圖表。


足夠的理論部分。讓我們繼續(xù)使用 GetX 教程進(jìn)行 Flutter 狀態(tài)管理,并在我們的應(yīng)用程序中實(shí)現(xiàn)它。


安裝 GetX


flutter pub 添加獲取

在Android studio/vs code的終端運(yùn)行上面的命令,它會(huì)添加最新的GetX插件到pubspec.yaml.

我們將在這個(gè)進(jìn)一步的教程中涵蓋三個(gè)部分
1. 基本計(jì)數(shù)器應(yīng)用程序的狀態(tài)管理
2. 使用 GetX 進(jìn)行導(dǎo)航
3. 在沒(méi)有上下文的情況下擴(kuò)充 UI 組件

提出您的需求,我們提供解決方案!
使用 Bacancy 開(kāi)發(fā)最佳、具有成本效益和高性能的 Flutter 應(yīng)用程序!停止浪費(fèi)您的時(shí)間并聯(lián)系我們聘請(qǐng) Flutter 開(kāi)發(fā)人員!

依賴(lài)注入

在 Getx 中,依賴(lài)注入允許您僅使用 1 行代碼來(lái)放置/檢索您的類(lèi)實(shí)例,不需要上下文來(lái)放置/檢索您的類(lèi)實(shí)例。


獲取.put(某些類(lèi)());獲取.lazyPut(() => SomeClass());

Get.put() 可幫助您在整個(gè)應(yīng)用程序中激活您的實(shí)例。
而 Get.lazyPut 通過(guò)在屏幕需要時(shí)實(shí)例化類(lèi)并稍后在不再需要時(shí)將其刪除來(lái)幫助您管理應(yīng)用程序內(nèi)存。

Getx 綁定

該軟件包的強(qiáng)大功能之一。通過(guò)使用它,您可以將屏幕連接到他們的控制器。因此,無(wú)論何時(shí)從小部件堆棧中移除屏幕,控制器中存在的所有流、變量和實(shí)例都將自動(dòng)從內(nèi)存中清除。

項(xiàng)目結(jié)構(gòu)

每個(gè)屏幕都進(jìn)入功能文件夾
在每一個(gè)屏幕上

  • 綁定:當(dāng)屏幕可見(jiàn)時(shí)需要實(shí)例化的控制器列表

  • 控制器:業(yè)務(wù)邏輯

  • Repository:包含對(duì)外部數(shù)據(jù)源的調(diào)用

  • 路線:PageRoute(包含有關(guān)名稱(chēng)、屏幕和綁定的信息)

  • 查看:您的屏幕/小部件

使用 GetX 教程進(jìn)行 Flutter 狀態(tài)管理

在這里,我將通過(guò)使用控制器分離 UI 邏輯和業(yè)務(wù)邏輯來(lái)創(chuàng)建一個(gè)計(jì)數(shù)器應(yīng)用程序,為此我將使用 Obx。如果您不知道這一切,請(qǐng)不要擔(dān)心;我正在一一詳細(xì)解釋所有這些。


您可以看到我使用推薦的 GetX 模式創(chuàng)建的項(xiàng)目結(jié)構(gòu),其中包含視圖、控制器和綁定類(lèi)。View 類(lèi)處理用于膨脹 UI 的代碼,該 UI 將出現(xiàn)在屏幕上。綁定類(lèi)將與特定頁(yè)面關(guān)聯(lián),在該類(lèi)中,我們可以實(shí)例化控制器類(lèi)。在控制器類(lèi)中,我們可以定義變量和業(yè)務(wù)邏輯函數(shù),在我們的例子中是增量函數(shù)。此外,在 main.dart 中,我們聲明了 GetMaterialApp 而不是 MaterialApp,因此我們可以使用 GetX 框架的所有功能。

CounterRepository 類(lèi)


抽象類(lèi) CounterRepository {
 常量計(jì)數(shù)器庫(kù)();
 處方藥計(jì)數(shù);
 無(wú)效增量();}類(lèi) CounterIncrementOneRepository 擴(kuò)展 CounterRepository {
 CounterIncrementOneRepository();
 @覆蓋
 最終處方計(jì)數(shù) = 0.obs;
 最終 int _incrementValue = 1;
 @覆蓋
 void increment() => count.value += _incrementValue;}

CounterRepository 提供了一種抽象,因此您可以在不影響您的表示層或業(yè)務(wù)邏輯層的情況下模擬底層數(shù)據(jù)源。

計(jì)數(shù)器控制器類(lèi)


類(lèi) CounterController 擴(kuò)展 GetxController {
 最終的 CounterRepository 回購(gòu);
 計(jì)數(shù)器控制器(this.repo);
 void navigateToReverseCounterScreen() {
   Get.offAllNamed(ReverseCounterRoute.name);
 }}

計(jì)數(shù)器控制器包含可在您的屏幕中使用的存儲(chǔ)庫(kù)實(shí)例和其他業(yè)務(wù)邏輯。這里我用.obs聲明了count變量,這意味著count是可觀察的,每當(dāng)這個(gè)值發(fā)生變化時(shí),我們可以通過(guò)控制器類(lèi)監(jiān)聽(tīng)那個(gè)值。與提供者不同,我們不需要調(diào)用notifylisteners。在增量函數(shù)中,我只是增加計(jì)數(shù)變量值。

反綁定類(lèi)


類(lèi) CounterBinding 實(shí)現(xiàn)綁定 {
 常量計(jì)數(shù)器綁定();
 @覆蓋
 無(wú)效依賴(lài)項(xiàng)(){
   Get.lazyPut(() => CounterController(CounterIncrementOneRepository()));
 }}

如前所述,Get.lazyPut() 可幫助您在需要時(shí)實(shí)例化您的控制器,例如當(dāng)您的屏幕對(duì)用戶可見(jiàn)時(shí),并在您的屏幕從小部件堆棧中移除時(shí)移除控制器。

CounterRoute類(lèi)


類(lèi) CounterRoute {
 常量 CounterRoute._();
 靜態(tài)常量字符串名稱(chēng) = '/';
 static const 綁定 binding = CounterBinding();
 static const 小部件屏幕 = CounterScreen();
 靜態(tài)最終 GetPage 頁(yè)面 = GetPage(
   姓名:姓名,
   綁定:綁定,
   頁(yè)面:()=>屏幕,
 );
 靜態(tài) GetPageRoute 獲取 pageRoute => GetPageRoute(
       設(shè)置:const RouteSettings(名稱(chēng):名稱(chēng)),
       綁定:綁定,
       頁(yè)面:()=>屏幕,
     );}

計(jì)數(shù)器路由包含您的路由相關(guān)信息,如名稱(chēng)、綁定和屏幕。

計(jì)數(shù)器屏幕類(lèi)


類(lèi) CounterScreen 擴(kuò)展 StatelessWidget {
 const CounterScreen({Key?key}) : super(key: key);
 @覆蓋
 小部件構(gòu)建(BuildContext 上下文){
   最終 CounterController 控制器 = Get.find();
   返回腳手架(
     應(yīng)用欄:應(yīng)用欄(
       title: const Text('計(jì)數(shù)器'),
     ),
     身體:中心(
       孩子:專(zhuān)欄(
         mainAxisAlignment:MainAxisAlignment.center,
         孩子們:[
           高架按鈕(
             onPressed: controller.navigateToReverseCounterScreen,
             child: const Text('Go to reverse counter screen'),
           ),
           const SizedBox(高度:16),
           常量文本(
             '你已經(jīng)按下按鈕這么多次了:',
           ),
           對(duì)象(
             () => 文本(
               '${controller.repo.count.value}',
               樣式:Theme.of(context).textTheme.headline4,
             ),
           ),
         ],
       ),
     ),
     浮動(dòng)操作按鈕:浮動(dòng)操作按鈕(
       onPressed: controller.repo.increment,
       工具提示:'增量',
       孩子:const Icon(Icons.add),
     ),
   );
 }}最終 CounterController 控制器 = Get.find();

上面一行提供了控制器的參考。

主要部分類(lèi)

要使您的 getx 綁定工作,您需要在 GetMaterialApp -> getPage 屬性中傳遞路由信息。在這里我們將使用我們已經(jīng)創(chuàng)建的main.dart 的CounterRoute 類(lèi)


無(wú)效主要(){
 runApp(const MyApp());}類(lèi) MyApp 擴(kuò)展 StatelessWidget {
 const MyApp({super.key});
 @覆蓋
 小部件構(gòu)建(BuildContext 上下文){
   返回 GetMaterialApp(
     title: 'Flutter Getx 演示',
     主題:主題數(shù)據(jù)(
       primarySwatch: Colors.blue,
     ),
     initialRoute: CounterRoute.name,
     獲取頁(yè)面:[
       CounterRoute.page,
       ReverseCounterRoute.page,
     ],
   );
 }}

為了測(cè)試 getx 綁定,我創(chuàng)建了一個(gè)與計(jì)數(shù)器相同的第二個(gè)屏幕,但它是一個(gè)反向計(jì)數(shù)器,因此當(dāng)用戶單擊減號(hào)按鈕時(shí),計(jì)數(shù)器將遞減

這是反向計(jì)數(shù)器中使用的所有文件


反向計(jì)數(shù)器存儲(chǔ)庫(kù)(僅從計(jì)數(shù)器存儲(chǔ)庫(kù)更改)


抽象類(lèi) ReverseCounterRepository {
 const ReverseCounterRepository();
 處方藥計(jì)數(shù);
 無(wú)效遞減();}類(lèi) ReverseCounterDecrementOneRepository 擴(kuò)展 ReverseCounterRepository {
 ReverseCounterDecrementOneRepository();
 @覆蓋
 最終處方計(jì)數(shù) = 0.obs;
 最終 int _decrementValue = 1;
 @覆蓋
 void decrement() => count.value -= _decrementValue;}

在這里您可以看到此存儲(chǔ)庫(kù)將值減一。這是在反向計(jì)數(shù)器屏幕中所做的唯一更改。


在這里,您可以看到當(dāng)用戶導(dǎo)航到計(jì)數(shù)器屏幕時(shí)創(chuàng)建和初始化 CounterController 的日志,以及當(dāng)用戶移動(dòng)到新屏幕時(shí)從內(nèi)存中刪除的日志

反向計(jì)數(shù)器控制器也是如此 ReverseCounterController 在用戶導(dǎo)航到反向計(jì)數(shù)器屏幕時(shí)創(chuàng)建和初始化,并在用戶移動(dòng)到新屏幕時(shí)從內(nèi)存中刪除

命名導(dǎo)航類(lèi)

在你的 MaterialApp 之前添加“Get”,將其變成 GetMaterialApp
并分配 initialRoute 和 getPages


類(lèi) MyApp 擴(kuò)展 StatelessWidget {
 const MyApp({super.key});
 @覆蓋
 小部件構(gòu)建(BuildContext 上下文){
   返回 GetMaterialApp(
     title: 'Flutter Getx 演示',
     主題:主題數(shù)據(jù)(
       primarySwatch: Colors.blue,
     ),
     initialRoute: CounterRoute.name, // 主頁(yè)路由
     getPages: [ // 路由/屏幕在整個(gè)應(yīng)用程序中可用
       CounterRoute.page,
       ReverseCounterRoute.page,
     ],
   );
 }}這里 CounterRoute.page 是靜態(tài)最終 GetPage 頁(yè)面 = GetPage(
   name: name, // 這個(gè)名字用來(lái)分配具名路由
   綁定:綁定,
   頁(yè)面:()=>屏幕,
 );導(dǎo)航到命名路線使用Get.toNamed('/some_page');Get.offNamed('/some_page');Get.offAllNamed('/some_page');Get.offNamedUtil('/some_page');

final CounterController counterController = Get.put(CounterController());

在構(gòu)建方法中使用上述語(yǔ)法,我已經(jīng)定義了控制器類(lèi)。文本按鈕將調(diào)用控制器類(lèi)中定義的增量方法,文本將顯示計(jì)數(shù)的更新值。但是你能看到的主要是文本小部件用 Obx 包裝,這意味著它可以獲取可觀察變量的值;沒(méi)有 Obx,價(jià)值就不會(huì)得到體現(xiàn)。

在這里,我使用一個(gè)簡(jiǎn)單的計(jì)數(shù)器應(yīng)用程序示例來(lái)輕松理解所有類(lèi)、結(jié)構(gòu)和狀態(tài)管理。我們可以使用 GetX flutter 通過(guò)遵循這種可觀察的模式并編寫(xiě)更清晰的代碼來(lái)實(shí)現(xiàn)更多。

讓我們深入到導(dǎo)航部分。

在狀態(tài)管理塊中附帶的屏幕截圖中,我們還創(chuàng)建了一個(gè)名為 home 的頁(yè)面。因此,假設(shè)我們需要單擊一次按鈕從計(jì)數(shù)器類(lèi)轉(zhuǎn)到主頁(yè)。我們可以簡(jiǎn)單地調(diào)用 GetX 導(dǎo)航塊,如下所示。

Get.to(HomeView());

很簡(jiǎn)單。不是嗎?無(wú)需調(diào)用大量樣板代碼,我們可以簡(jiǎn)單地調(diào)用它并移動(dòng)到不同的屏幕。此外,還有不同的選項(xiàng)可以重定向到另一個(gè)頁(yè)面。

例如,您可以簡(jiǎn)單地將主屏幕替換為下面當(dāng)前打開(kāi)的屏幕。這意味著將被替換的當(dāng)前屏幕不會(huì)在堆棧中。

Get.off(HomeView());

而且,如果我們需要?jiǎng)h除所有以前的堆棧,我們可以調(diào)用Get.off(HomeView());

Get.offAll(HomeView());

除此之外,我們可以在路由之間傳遞數(shù)據(jù)并在打開(kāi)另一個(gè)路由之前顯示動(dòng)畫(huà),并使用 flutter GetX 打開(kāi)一個(gè)屏幕作為對(duì)話框。

現(xiàn)在讓我們轉(zhuǎn)到?jīng)]有上下文的 Inflating UI 組件的最后一點(diǎn)。

在沒(méi)有上下文的情況下膨脹 UI 組件

傳統(tǒng)上,打開(kāi)對(duì)話框或底部工作表。如果您有一個(gè)單獨(dú)的文件來(lái)處理通用小部件,我們還需要將上下文傳遞給該類(lèi)。但是對(duì)于 GetX,情況并非如此。我們可以在不使用上下文的情況下以更簡(jiǎn)單的方式簡(jiǎn)單地膨脹那種 UI 塊。

顯示小吃店


Get.snackbar('This is snackbar', 'This is snackbar message', backgroundColor: Colors.red);

顯示對(duì)話框


Get.defaultDialog(
  title: '這是對(duì)話',
  middleText: '這是中間文本',
  buttonColor: Colors.green,
  textCancel: "取消",
  textConfirm: "確認(rèn)");

顯示底頁(yè)


Get.bottomSheet(
容器(
  孩子:包裹(
    孩子們: [
      列表塊(
        領(lǐng)先:圖標(biāo)(Icons.wb_sunny_outlined),
        title: Text("淺色主題"),
        onTap: () => {Get.changeTheme(ThemeData.light())},
      ),
      列表塊(
        領(lǐng)先:圖標(biāo)(Icons.wb_sunny),
        title: Text("深色主題"),
        onTap: () => {Get.changeTheme(ThemeData.dark())},
      )
    ],
  ),
),
背景顏色:Colors.green);

我想這就是 GetX 的目的。您可以通過(guò)以下官方鏈接來(lái)探索有關(guān) GetX 的更多信息。
https://pub.dev/packages/get

借助 Git Cli 插件,您可以使項(xiàng)目結(jié)構(gòu)更加順暢。您可以查看下面的鏈接。
https://pub.dev/packages/get_cli

結(jié)論

以上就是使用 GetX 進(jìn)行 Flutter 狀態(tài)管理的教程。如果您是 Flutter 愛(ài)好者,Flutter 教程頁(yè)面適合您!試用教程并開(kāi)始在您的應(yīng)用程序中實(shí)施它們。如果您有任何建議、疑問(wèn)或問(wèn)題,請(qǐng)給我們回信。

言鼎科技主做軟件開(kāi)發(fā),微信小程序,網(wǎng)站開(kāi)發(fā),軟件外包,手機(jī)APP開(kāi)發(fā)。如有需要記得聯(lián)系我們!

The End