3月5日,閒魚宣佈在GitHub上開源Fish Redux,Fish Redux是一個基於 Redux 數據管理的組裝式 flutter 應用框架, 特別適用於構建中大型的複雜應用,它最顯著的特徵是 函數式的編程模型、可預測的狀態管理、可插拔的組件體系、最佳的性能表現。下文中,咱們將詳細介紹Fish Redux的特色和使用過程,如下內容來自InfoQ獨家對閒魚Flutter團隊的採訪和Fish Redux的開源文檔。前端
在閒魚接入Flutter之初,因爲咱們的落地的方案但願是從最複雜的幾個主鏈路進行嘗試來驗證flutter完備性的,而咱們的詳情總體來說業務比較複雜,主要體如今兩個方面:git
在咱們嘗試使用市面上已有的框架(google提供的redux以及bloc)的時候發現,沒有任何一個框架能夠既解決集中狀態管理,又能解決UI的組件化的,由於自己這兩個問題有必定的矛盾性(集中vs分治)。所以咱們但願有一套框架能解決咱們的問題,fish redux應運而生。程序員
fish redux自己是通過比較屢次的迭代的,目前你們看到的版本通過了3次比較大的迭代,實際上也是通過了團隊比較多的討論和思考。github
第一個版本是基於社區內的flutter_redux進行的改造,核心是提供了UI代碼的組件化,固然問題也很是明顯,針對複雜的詳情和發佈業務,每每業務邏輯不少,沒法作到邏輯代碼的組件化。編程
第二個版本針對第一個版本的問題,作出了比較重大的修改,解決了UI代碼和邏輯代碼的分治問題,但同時,按照redux的標準,打破了redux的原則,對於精益求精的閒魚團隊來說,不能接受;redux
所以,在第三個版本進行重構時,咱們確立了總體的架構原則與分層要求,一方面按照reduxjs的代碼進行了flutter側的redux實現,將redux的原則完整保留下來。另外一方面針對組件化的問題,提供了redux之上的component的封裝,並創新的經過這一層的架構設計提供了業務代碼分治的能力。性能優化
至此,咱們完成了fish redux的基本設計,但在後續的應用中,發現了業務組裝之後的代碼性能問題,針對該問題,咱們再次提供了對應的adapter能力,保障了在長列表場景下的big cell問題。目前,fish redux已經在線上穩定運行超過3個月以上,將來,期待fish redux給社區帶來更多的輸入。架構
分層架構圖app
架構圖:主體自底而上,分兩層,每一層用來解決不通層面的問題和矛盾,下面依次來展開。框架
Redux 是來自前端社區的一個數據管理框架,對 Native開發同窗來講可能會有一點陌生,咱們作一個簡單的介紹。
Redux 是作什麼的?
Redux 是一個用來作可預測易調試的數據管理的框架。全部對數據的增刪改查等操做都由 Redux 來集中負責。
Redux 是怎麼設計和實現的?
Redux 是一個函數式的數據管理的框架。傳統 OOP 作數據管理,每每是定義一些 Bean,每個 Bean 對外暴露一些 Public-API 用來操做內部數據(充血模型)。
函數式的作法是更上一個抽象的緯度,對數據的定義是一些 Struct(貧血模型),而操做數據的方法都統一到具備相同函數簽名 (T, Action) => T 的 Reducer 中。
FP:Struct(貧血模型) + Reducer = OOP:Bean(充血模型)
同時 Redux 加上了 FP 中經常使用的 Middleware(AOP) 模式和 Subscribe 機制,給框架帶了極高的靈活性和擴展性。
貧血模型、充血模型請參考:
https://en.wikipedia.org/wiki/Plain_old_Java_object
Redux 的缺點
Redux 核心僅僅關心數據管理,不關心具體什麼場景來使用它,這是它的優勢同時也是它的缺點。
在咱們實際使用 Redux 中面臨兩個具體問題:
Fish Redux 經過 Redux 作集中化的可觀察的數據管理。然不只於此,對於傳統 Redux 在使用層面上的缺點,在面向端側 flutter 頁面緯度開發的場景中,咱們經過更好更高的抽象,作了改良。
一個組件須要定義一個數據(Struct)和一個 Reducer。同時組件之間存在着父依賴子的關係。經過這層依賴關係,
咱們解決了【集中】和【分治】之間的矛盾,同時對 Reducer 的手動層層 Combine 變成由框架自動完成,大大簡化了使用 Redux 的困難。
咱們獲得了理想的集中的效果和分治的代碼。
State、Action、Reducer、Store、Middleware 以上概念和社區的 ReduxJS 是徹底一致的。咱們將原汁原味地保留全部的 Redux 的優點。
若是想對 Redux 有更近一步的理解,請參考:https://github.com/reduxjs/redux
組件是對局部的展現和功能的封裝。 基於 Redux 的原則,咱們對功能細分爲修改數據的功能(Reducer)和非修改數據的功能(反作用 Effect)。
因而咱們獲得了,View、 Effect、Reducer 三部分,稱之爲組件的三要素,分別負責了組件的展現、非修改數據的行爲、修改數據的行爲。
這是一種面向當下,也面向將來的拆分。在面向當下的 Redux 看來,是數據管理和其餘。在面向將來的 UI-Automation 看來是 UI 表達和其餘。
UI 的表達對程序員而言即將進入黑盒時代,研發工程師們會把更多的精力放在非修改數據的行爲、修改數據的行爲上。
組件是對視圖的分治,也是對數據的分治。經過逐層分治,咱們將複雜的頁面和數據切分爲相互獨立的小模塊。這將利於團隊內的協做開發。
View 僅僅是一個函數簽名: (T,Dispatch,ViewService) => Widget
它主要包含三方面的信息
Effect 是對非修改數據行爲的標準定義,它是一個函數簽名: (Context, Action) => Object
它主要包含四方面的信息
好比良好的協程的支持:
Reducer 是一個徹底符合 Redux 規範的函數簽名:(T,Action) => T
一些符合簽名的 Reducer:
同時咱們以顯式配置的方式來完成大組件所依賴的小組件、適配器的註冊,這份依賴配置稱之爲 Dependencies。
因此有這樣的公式 Component = View + Effect(可選) + Reducer(可選) + Dependencies(可選)。
一個典型的組裝:
經過 Component 的抽象,咱們獲得了完整的分治,多緯度的複用,更好的解耦。
Adapter 也是對局部的展現和功能的封裝。它爲 ListView 高性能場景而生,它是 Component 實現上的一種變化。
它的目標是解決 Component 模型在 flutter-ListView 的場景下的 3 個問題:
1)將一個"Big-Cell"放在 Component 裏,沒法享受 ListView 代碼的性能優化;
2)Component 沒法區分 appear|disappear 和 init|dispose ;
3)Effect 的生命週期和 View 的耦合,在 ListView 的場景下不符合直觀的預期。
歸納的講,咱們想要一個邏輯上的 ScrollView,性能上的 ListView ,這樣的一種局部展現和功能封裝的抽象。作出這樣獨立一層的抽象是咱們看實際的效果,咱們對頁面不使用框架Component,使用框架 Component+Adapter 的性能基線對比。
咱們經過不斷的測試作對比,以某 Android機爲例:
推薦的目錄結構會是這樣
sample_page -- action.dart -- page.dart -- view.dart -- effect.dart -- reducer.dart -- state.dart components sample_component -- action.dart -- component.dart -- view.dart -- effect.dart -- reducer.dart -- state.dart
上層負責組裝,下層負責實現, 同時會有一個插件提供, 便於咱們快速填寫。
以閒魚的詳情場景爲例的組裝:
組件和組件之間,組件和容器之間都徹底的獨立。
簡單的描述:採用的是帶有一段優先處理的廣播, self-first-broadcast。
發出的 Action,本身優先處理,不然廣播給其餘組件和 Redux 處理。最終咱們經過一個簡單而直觀的 dispatch 完成了組件內,組件間(父到子,子到父,兄弟間等)的全部的通訊訴求。
數據刷新
層層的數據的拷貝:
視圖刷新
扁平化通知到全部組件,組件經過 shouldUpdate 肯定本身是否須要刷新。
數據的集中管理
經過 Redux 作集中化的可觀察的數據管理。咱們將原汁原味地保留全部的 Redux 的優點,同時在 Reducer 的合併上,變成由框架代理自動完成,大大簡化了使用 Redux 的繁瑣度。
組件的分治管理
組件既是對視圖的分治,也是對數據的分治。經過逐層分治,咱們將複雜的頁面和數據切分爲相互獨立的小模塊。這將利於團隊內的協做開發。
View、Reducer、Effect 隔離
將組件拆分紅三個無狀態的互不依賴的函數。由於是無狀態的函數,它更易於編寫、調試、測試、維護。同時它帶來了更多的組合、複用和創新的可能。
聲明式配置組裝
組件、適配器經過自由的聲明式配置組裝來完成。包括它的 View、Reducer、Effect 以及它所依賴的子項。
良好的擴展性
核心框架保持本身的核心的三層關注點,不作核心關注點之外的事情,同時對上層保持了靈活的擴展性。
精小、簡單、完備
開源以後,閒魚打算經過如下方式來維護Fish Redux:
Fish Redux 目前已在阿里巴巴閒魚技術團隊內多場景,深刻應用。最後 Talk is cheap, Show me the code,咱們今天正式在GitHub上開源,更多內容,請到GitHub瞭解。
GitHub地址:https://github.com/alibaba/fish-redux
本文爲雲棲社區原創內容,未經容許不得轉載。