使用 GetX 進(jìn)行 Flutter 狀態(tài)管理
介紹
每當(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)航部分。
使用 GetX 導(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)系我們!