Flutter高內聚元件怎麼做?閒魚打造開源高效方案!
fish_redux是閒魚技術團隊打造的開源flutter應用開發框架,旨在解決頁面內元件間的高內聚、低耦合問題。開源地址:
從react_redux說起
redux對於前端的同學來說是一個比較熟悉的框架了,fish_redux借鑑了redux單項資料流思想。在flutter上說到redux,大家可能第一反應會類比到react上的react_redux。在react_redux中有個重要的概念——connect,
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
簡單得說,connect允許使用者從Redux store中獲取資料並繫結到元件的props上,可以dispatch一個action去修改資料。
那麼fish_redux中的connector是做什麼的呢?為什麼說connector解決了元件內聚的問題?我們應該如何理解它的設計呢?
connector in fish_redux
儘管都起到了連線的作用,但fish_redux與react_redux在抽象層面有很大的不同。
fish_redux本身是一個flutter上的應用框架,建立了自己的component體系,用來解決元件內的高內聚和元件間的低耦合。從connector角度來說,如何解決內聚問題,是設計中的重要考量。
fish_redux自己製造了 Component
樹, Component
聚合了state和dispatch,每一個子 Component
的state透過 connector
從父 Component
的state中篩選。如圖所示:
可以看到,fish_redux的connector的主要作用把父子 Component
關聯起來,最重要的操作是filter。state從上之下是一個嚴謹的樹形結構,它的結構複用了 Component
的樹形結構。類似一個漏斗形的資料管道,管理資料的分拆與組裝。它表達瞭如何組裝一個 Component
。
而對於react_redux來說,它主要的作用在於把react框架和redux繫結起來,重點在於如何讓React component具有Redux的功能。
從圖中可以看到,react_redux和React是平行的結構,經過 mapStateToProps
後的state也不存在嚴謹的樹形結構,即對於一個React component來說,它的state來自於Redux store而不是父component的state。從框架設計的角度來說,react_redux最重要的一個操作就是attach。
原始碼分析
說完概念,我們從原始碼的角度來看看fish_redux中的connector是如何運作的,以fish_redux提供的example為例。
class ToDoListPage extends Page<PageState, Map> { ToDoListPage() : super( ... dependencies: Dependencies( adapter: ToDoListAdapter(), slots: <String, Dependent>{ 'report': ReportConnector() + ReportComponent() }), ... ); }
在ToDoListPage的建構函式中,向父類構造傳遞了一個 Dependencies
物件,在構造 Dependencies
時,引數 slots
中包含了名叫"report"的item,注意這個item的生成,是由一個 ReportConnector
+ ReportComponent
產生的。
從這裡我們得出一個簡單卻非常重要的結論:
在fish_redux中,一個Dependent = connector + Component 。
Dependent
代表頁面拼裝中的一個單元,它可以是一個 Component
(透過buildComponent函式產生),也可以是一個 Adapter
(由buildAdapter函式產生)。這樣設計的好處是,對於View拼裝操作來說, Dependent
對外統一了API而不需要透出更多的細節。
根據上面我們得出的結論, connector
用來把一個更小的 Component
單元連結到一個更大的 Component
或 Adapter
上。這與我們之前的描述相符合。
connector到底是什麼?
知道了 connector
的基本作用,我們來看一下它到底連結了哪些東西以及如何連結。
先來看一下ReportConnector類的定義:
class ReportConnector extends ConnOp
ReportConnector
繼承了 ConnOp
類,所有 connector
的操作包括+操作,都來自於 ConnOp
類。
set/get
既然是資料管道,就會有獲取和放置。
set
函式的入參很好得表達了 T
和 P
的意思,即把一個 P
型別的 subState
合併到 T
型別的 state
中。
再回頭看 get
函式,就很好理解了, get
函式表達的就是如何從 T
型別的 state
中獲取 P
型別的 subState
供 Dependent
使用。
operator +
+
運算子的過載是我們最初看到connector作用的地方,也是connector發揮作用的入口。
Logic
是 Component
和 Adapter
的父類,它表示頁面組裝元素的邏輯層,裡面包含了 reducer
/ effect
/ higherEffect
等與邏輯相關的元素以及它的組裝過程。
operator +
呼叫了 createDependent
函式,接著會呼叫到 _Dependent
類的建構函式,這裡將 logic
和 connector
放入 _Dependent
內部,在後面fish_redux對 Component
組裝的過程中,connector會隨著外部對 _Dependent
中函式的呼叫發揮作用。
connector正式登場
鋪墊了這麼多,是該connector正式發揮作用的時候了。
get
我們以 Component
為例,會呼叫到 _Dependent
的 buildComponent
函式:
Widget buildComponent(MixedStore store, Get getter) { final AbstractComponent component = logic; return component.buildComponent(store, () => connector.get(getter())); }
這裡的 logic
實際就是一個 Component
物件,在呼叫 Component
的 buildComponent
函式的時候,使用 get
函式從一個大的父state中獲取到當前 Component
需要的資料集。接下去,這個變換後的子state將被用在例如 ViewBuilder
或 Redcuer
函式中。
這是connector在資料獲取上的作用。
set
還是在 _Dependent
類裡面,看 createSubReducer
函式:
SubReducer createSubReducer() { final Reducer reducer = logic.reducer; return reducer != null ? connector.subReducer(reducer) : null; }
首現從一個 Logic
(這裡實際上是一個 Component
)物件中獲取到外部設定進來的 reducer
,接著呼叫 subReducer
返回一個 SubReducer
物件。 SubReducer
是一個被wrap後的 Reducer。
subReducer
的實現在 MutableConn
中, ConnOp
繼承了 MutableConn
類,也獲得了這個能力。
SubReducer subReducer(Reducer reducer) { return (T state, Action action, bool isStateCopied) { final P props = get(state); if (props == null) { return state; } final P newProps = reducer(props, action); final bool hasChanged = newProps != props; final T copy = (hasChanged && !isStateCopied) ? _clone(state) : state; if (hasChanged) { set(copy, newProps); } return copy; }; }
它首現透過 get
函式得到一個變換後的資料集 props
,接著呼叫原始的 reducer
函式進行邏輯處理,這裡有一個最佳化也是 SubReducer
的作用,如果資料集在經過 reducer
處理之後發生了變化,
並且state已經被copy過一次了(isStateCopied==true),就直接把 newProps
透過 set
函式更新到state中去。(這個最佳化可以防止多個子state發生變化的時候父state被複製多次)。
至此,connector在資料更新上的作用也體現出來了。
ReportConnector
最後,就好理解ReportConnector的實現了:
class ReportConnector extends ConnOp<PageState, ReportState> {
@override
ReportState get(PageState state) {
final ReportState reportState = ReportState();
reportState.total = state.toDos.length;
reportState.done =
state.toDos.where((ToDoState tds) => tds.isDone).toList().length;
return reportState;
}
@override
void set(PageState state, ReportState subState) {}
}
很明顯的,在 get
函式中, ReportState
從 PageState
中獲得了total/done欄位。
總結
閒魚客戶端的詳情頁完全使用了fish_redux進行了重構,透過高內聚的 Component+connector
形式,使得 Component
可以被大量複用,很好得支援了5種型別的詳情頁。未來我們會基於fish_redux強大的擴充套件能力製作更多元件來滿足不同業務對於框架的需求。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900359/viewspace-2645351/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Flutter高內聚元件怎麼做?閒魚閒魚打造開源高效方案!Flutter元件
- 在閒魚,我們如何用Dart做高效後端開發?Dart後端
- 來了!閒魚技術團隊開源Flutter應用框架Fish ReduxFlutter框架Redux
- 來了!閒魚技術團隊開源 Flutter 應用框架 Fish ReduxFlutter框架Redux
- 我是怎麼做開源的
- Flutter元件化開發方案Flutter元件化
- 閒魚又一企業級鉅著《Flutter in action》開放下載Flutter
- Flutter仿閒魚底部導航欄實現Flutter
- GMTC-閒魚Flutter實踐效果訪談Flutter
- 閒魚APP關聯同款寶貝怎麼設定?閒魚關聯同款寶貝的設定方法APP
- 新手做閒魚賣貨,自己找貨源一定注意這些坑?
- 閒魚Flutter&FaaS雲端一體化架構Flutter架構
- NOW直播——Flutter元件化開發方案Flutter元件化
- 閒魚Flutter互動引擎系列——整體設計篇Flutter
- 閒魚如何高效承接並處理使用者糾紛
- 閒魚"同款"的Flutter圖片下載功能(demo版)Flutter
- Flutter Worker —— 閒魚這樣實現“邏輯跨平臺”Flutter
- [閒魚技術] Release Flutter的最後一公里Flutter
- 承載億級流量的開發框架,閒魚 Flutter 技術解析與實戰大公開框架Flutter
- 軟體工程-----高內聚低耦合軟體工程
- 程式設計師怎麼高效做筆記程式設計師筆記
- Flutter動畫 5 - Flutter內建動畫元件Flutter動畫元件
- 開源 | FLUI : Flutter 的元件擴充套件集UIFlutter元件套件
- [閒魚技術] Flutter React程式設計正規化實踐FlutterReact程式設計
- 【安卓綠色聯盟開發者大會】閒魚Flutter分享實錄安卓Flutter
- 餐飲行業私域運營怎麼做,方案包括哪些內容行業
- 高內聚,低耦合的實現方式
- 閒魚基於Flutter技術的架構演進和創新Flutter架構
- 開源 高效能 高可用 可擴充套件套件
- 已開源!Flutter 流暢度優化元件 KeframeFlutter優化元件
- 為什麼閒魚爆款突然不出單了?給你三個快速解決方案!
- 一個高仿閒魚鍵自定義數字鍵盤特效特效
- 室內三維地圖怎麼做的?室內地圖怎麼做好看?地圖
- 重磅首發 | 承載億級流量的開發框架,閒魚 Flutter 技術解析與實戰大公開框架Flutter
- Java 工程解耦即高內聚低耦合Java解耦
- 閒魚專家詳解:Flutter React程式設計正規化實踐FlutterReact程式設計
- 開源179個Flutter元件的詳細使用介紹Flutter元件
- [譯] MDC-104 Flutter:Material 高階元件(Flutter)Flutter元件