Flutter狀態管理新的實踐

来源:https://www.cnblogs.com/Jcloud/archive/2023/06/20/17494256.html
-Advertisement-
Play Games

聲明式UI其實並不是近幾年的新技術,但是近幾年聲明式UI框架非常的火熱。單說移動端,跨平臺方案有:RN、Flutter。iOS原生有:SwiftUI。android原生有:compose。可以看到聲明式UI是以後的前端發展趨勢。而狀態管理是聲明式UI框架的重要組成部分。 ...


1 背景介紹

1.1 聲明式ui

聲明式UI其實並不是近幾年的新技術,但是近幾年聲明式UI框架非常的火熱。單說移動端,跨平臺方案有:RN、Flutter。iOS原生有:SwiftUI。android原生有:compose。可以看到聲明式UI是以後的前端發展趨勢。而狀態管理是聲明式UI框架的重要組成部分。

1.2 聲明式UI框架的狀態

在移動端之前的命令式UI框架,沒有狀態的概念。每個控制項其實都是無狀態的,我們要更新UI需要手動的去set。命令式UI引入狀態的概念,狀態可以理解為訂閱了控制項所依賴數據的變化,當一個控制項依賴的數據發生變化時,自動刷新UI展示。最大的優勢就是可以很方便的做到UI和邏輯的解耦。

2 provider狀態管理

2.1 使用方式

定義一個頁面如下:

實現功能,當點擊“按鈕”的時候,更新“你好”這個組件
頁面部分代碼實現(基於StatelessWidget實現):

model部分實現:

2.2 問題和不足

點擊“按鈕”的時候查看頁面刷新,發現下表羅列的Widget都執行了刷新操作,使用Selector雖然被包裹的內容沒有刷新,但是需要進行校驗操作。

2.2.1 控制項刷新

2.2.2 問題分析

  1. 使用不太靈活,想要消費事件刷新UI必須有頂層的Provider提供model,在一些複雜場景可能會增加邏輯複雜度
  2. 狀態刷新,不能實現最小粒度的管理
  3. 代碼不夠簡潔

3 新的狀態管理方式實踐

3.1 使用方式

實現同樣的上述頁面邏輯,代碼如下(同樣基於StatelessWidget實現):
首先不需要依賴外部的provider提供Model,任何想要獨立刷新的區域使用TosObWidget控制項包裹即可,使用比較靈活,我們可以把TosObWidget插入到任何我們想要的位置(包括provider內),代碼邏輯比較簡潔

model實現:

model的實現更加簡潔,不需要繼承ChangeNotifier,所以可以把狀態數據定義在任何我們想要的地方,使用.tos擴展屬性返回一個包含預設值的RxObj對象,當我們使用set方法更改RxObj的value的時候,通知依賴此對象的TosObWidget區域進行刷新,例:我們點擊按鈕的時候,_model.textA.value = “你好${_model.i++}”,執行後就會刷新依賴textA的TosObWidget(() => Text(_model.textA.value))區域

查看刷新狀態(與provider對比):

對比發現TosObWidget這種方式,只有依賴的數據發生變化的TosObWidget才會更新狀態,可以實現狀態刷新粒度最小化,提高性能

3.2 設計思路

3.2.1 TosObWidget

首先是使用入口,定義一個TosObWidget控制項,入參為build函數,返回widget,每個TosObWidget就是一個可獨立進行狀態刷新的區域

TosObWidget控制項的實現如下:

TosObWidget的build函數為重載的其父類_ObzWidget的build函數,最終會被_ObzWidget的_ObzState調用,_ObzWidget的實現如下:

接下來查看_ObzState的實現,主要邏輯都在這個類進行實現,這裡貼出所有的代碼(註意框起來的邏輯):

3.2.2 TosObWidget邏輯分析

  1. 首先_ObzState依賴一個RxObserver _observer變數
  2. RxObserver _observer這個 變數持有了_updateUI()這個方法,最終會通過這個方法刷新TosOBWidget的狀態
  3. 當TosObWidget執行build的時候,會通過一個靜態變數RxObserver.proxy把_observer共用出去
  4. 這樣TosObWidget包裹的內容,使用RxObj的getValue的時候會拿到被共用的_observer,這時建立RxObj和TosObWidget的聯繫
  5. 聯繫建立後,重置共用變數RxObserver.proxy
  6. 這樣在RxObj的value執行set方法時,會調用到與其綁定的TosObWidget的_updateUI()這個函數

3.2.3 RxObj的實現

如下貼出RxObj的value的get和set函數:

  1. 當執行RxObj的value的get方法時,代碼如下,拿到 RxObserver的靜態成員變數proxy,類型為RxObserver(即為上一步TosObWidget共用出來的_observer)
  2. 判斷RxObserver.proxy不為空,且沒有被添加到_observers列表( List _observers),則添加
  3. 當執行RxObj的value的set方法時,校驗value是否與當前的value值相同,且判斷是否是首次創建(首次創建不會執行狀態刷新)
  4. 校驗完成後則賦值執行refresh()函數,更新TosObWidget的狀態

refresh()函數的實現如下:
observer.update()函數即為執行與Rxobj關聯的TosObWidget的_updateUI()函數:

看下RxObserver的實現:
註意框起來的邏輯,update函數即上面_ObzState的_updateUI()函數的引用

至此整個實現流程已經貫通了,接下來看下如何使用:

1)通過.tos擴展屬性定義RxObj變數:

2).tos擴展屬性的實現如下:

3)如果要創建一個預設值為空的,RxObj實例,使用如下方式:

此時如果我們使用RxObj的setValue方法,就會刷新依賴它的所有TosObWidget控制項,如果有些情況下,沒有調用setValue方法,但是需要刷新狀態,可手動調用refresh()方法,實現如下:

至此,就完成了TosObWidget控制項的狀態刷新

4 總結

註:基於本文示例的功能邏輯進行對比

作者:京東物流 張俊飛

來源:京東雲開發者社區


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • >原本只是想要每次打開終端,預設是 zsh ,方便使用 oh-my-zsh。但誰能料到這個配置有個史前大坑! ## 問題復現 頂部菜單欄的`終端` > 首選項配置:`未命名` > `命令` > 運行自定義命令 > 命令退出時:退出終端。 **只要這條命令出錯,或者執行完畢,就會結束退出了** (太痛 ...
  • ## 使用(微軟賬戶)進行遠程桌面連接 1. 打開找到[查看高級系統設置] -> [遠程] -> [遠程桌面]。 ![image](https://img2023.cnblogs.com/blog/3081210/202306/3081210-20230620213008346-1294112930 ...
  • logstash在需要收集日誌的伺服器里運行,將日誌數據發送給es 在kibana頁面查看es的數據 es和kibana安裝: Install Elasticsearch with RPM | Elasticsearch Guide [8.8] | Elastic Configuring Elast ...
  • ##[Ooonly新人貼]記錄工作中遇到的問題,話不多說先上乾貨 問題:類似K線與藍牙接收部門模塊,要求由原來的接收串口中斷改為DMA接收。據說要用到空閑中斷與DMA中斷,但是經模擬發現DMA每完成傳輸一個數據(比如1BYTE)就會進入空閑中斷(k線發現這種情況),考慮到這樣進入中斷的頻率和以前串口 ...
  • 更改緩衝區(Change Buffer)是一種特殊的數據結構,用於緩存不在緩衝池中的二級索引(secondary index)頁的更改。可能來自於 INSERT、UPDATE 或 DELETE 操作(數據操作語言,DML)的緩衝更改,會在後續通過其他讀操作將這些頁載入到緩衝池時被合併。 ...
  • 摘要:華為宣佈實現了自主創新的MetaERP研發,並且完成了對舊ERP系統的全面替換,這其中,就採用了華為雲GaussDB資料庫特有的全密態技術,對ERP系統中的絕密數據進行加密保護,從而保障了數據的安全。 ERP系統在幫助企業優化業務流程、實現數字化管理方面有重要作用,可以說企業所有的業務流轉都需 ...
  • 摘要:HyG圖計算引擎採用CSR格式來存儲圖的拓撲信息,CSR格式可以將稀疏矩陣的存儲空間壓縮,進而大大降低圖的存儲開銷,同時具備訪問效率高、格式易轉化等優點。 本文分享自華為雲社區《CSR格式如何更新? GES圖計算引擎HyG揭秘之數據更新》,作者: π 。 HyG圖計算引擎採用CSR格式來存儲圖 ...
  • MVCC併發版本控制 本文大部分來自《MySQL是怎樣運行的》,這裡只是簡單總結,用於各位回憶和複習。 版本鏈 對於使用 InnoDB 存儲引擎的表來說,它的聚簇索引記錄中都包含兩個必要的隱藏列(不知道的快去看《MySQL是怎樣運行的》) trx_id :每次一個事務對某條聚簇索引記錄進行改動時,都 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...