日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Fish Redux中的Dispatch是怎么实现的?

發(fā)布時間:2024/8/23 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Fish Redux中的Dispatch是怎么实现的? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

零.前言

我們在使用fish-redux構(gòu)建應(yīng)用的時候,界面代碼(view)和事件的處理邏輯(reducer,effect)是完全解耦的,界面需要處理事件的時候?qū)ction分發(fā)給對應(yīng)的事件處理邏輯去進行處理,而這個分發(fā)的過程就是下面要講的dispatch, 通過本篇的內(nèi)容,你可以更深刻的理解一個action是如何一步步去進行分發(fā)的。

一.從example開始

為了更好的理解action的dispatch過程,我們就先以todo_list_page中一條todo條目的勾選事件為例,來看點擊后事件的傳遞過程,通過斷點debug我們很容易就能夠發(fā)現(xiàn)點擊時候發(fā)生的一切,具體過程如下:

  • 用戶點擊勾選框,GestureDetector的onTap會被回調(diào)
  • 通過buildView傳入的dispatch函數(shù)對doneAction進行分發(fā),發(fā)現(xiàn)todo_component的effect中無法處理此doneAction,所以將其交給pageStore的dispatch繼續(xù)進行分發(fā)
  • pageStore的dispatch會將action交給reducer進行處理,故doneAction對應(yīng)的_markDone會被執(zhí)行,對state進行clone,并修改clone后的state的狀態(tài),然后將這個全新的state返回
  • 然后pageStore的dispatch會通知所有的listeners,其中負(fù)責(zé)界面重繪的_viewUpdater發(fā)現(xiàn)state發(fā)生變化,通知界面進行重繪更新
  • 二.Dispatch實現(xiàn)分析

    Dispatch在實現(xiàn)的過程中借鑒了Elm。

    Dispatch在fish-redux中的定義如下

    typedef Dispatch = void Function(Action action);

    本質(zhì)上就是一個action的處理函數(shù),接受一個action,然后對action進行分發(fā)。

    下面我門通過源碼來進行詳細(xì)的分析

    1.component中的dispatch

    buildView函數(shù)傳入的dispatch是對應(yīng)的component的mainCtx中的dispatch,
    _mainCtx和componet的關(guān)系如下
    component -> ComponentWidget -> ComponentState -> _mainCtx -> _dispatch
    而 _mainCtx的初始化則是通過componet的createContext方法來創(chuàng)建的,順著方法下去我們看到了dispatch的初始化

    // redux_component/context.dart DefaultContext初始化方法DefaultContext({@required this.factors,@required this.store,@required BuildContext buildContext,@required this.getState,}) : assert(factors != null),assert(store != null),assert(buildContext != null),assert(getState != null),_buildContext = buildContext {final OnAction onAction = factors.createHandlerOnAction(this);/// create Dispatch_dispatch = factors.createDispatch(onAction, this, store.dispatch);/// Register inter-component broadcast_onBroadcast =factors.createHandlerOnBroadcast(onAction, this, store.dispatch);registerOnDisposed(store.registerReceiver(_onBroadcast));}

    context中的dispatch是通過factors來進行創(chuàng)建的,factors其實就是當(dāng)前component,factors創(chuàng)建dispatch的時候傳入了onAction函數(shù),以及context自己和store的dispatch。onAction主要是進行Effect處理。
    這邊還可以看到,進行context初始化的最后,還將自己的onAction包裝注冊到store的廣播中去,這樣就可以接收到別人發(fā)出的action廣播。

    Component繼承自Logic

    // redux_component/logic.dart@overrideDispatch createDispatch(OnAction onAction, Context<T> ctx, Dispatch parentDispatch) {Dispatch dispatch = (Action action) {throw Exception('Dispatching while appending your effect & onError to dispatch is not allowed.');};/// attach to store.dispatchdispatch = _applyOnAction<T>(onAction, ctx)(dispatch: (Action action) => dispatch(action),getState: () => ctx.state,)(parentDispatch);return dispatch;}static Middleware<T> _applyOnAction<T>(OnAction onAction, Context<T> ctx) {return ({Dispatch dispatch, Get<T> getState}) {return (Dispatch next) {return (Action action) {final Object result = onAction?.call(action);if (result != null && result != false) {return;}//skip-lifecycle-actionsif (action.type is Lifecycle) {return;}if (!shouldBeInterruptedBeforeReducer(action)) {ctx.pageBroadcast(action);}next(action);};};};} }

    上面分發(fā)的邏輯大概可以通過上圖來表示

  • 通過onAction將action交給component對應(yīng)的effect進行處理
  • 當(dāng)effect無法處理此action,且此action非lifecycle-actions,且不需中斷則廣播給當(dāng)前Page的其余所有effects
  • 最后就是繼續(xù)將action分發(fā)給store的dispatch(parentDispatch傳入的其實就是store.dispatch)
  • 2. store中的dispatch

    從store的創(chuàng)建代碼我們可以看到store的dispatch的具體邏輯

    // redux/create_store.dartfinal Dispatch dispatch = (Action action) {_throwIfNot(action != null, 'Expected the action to be non-null value.');_throwIfNot(action.type != null, 'Expected the action.type to be non-null value.');_throwIfNot(!isDispatching, 'Reducers may not dispatch actions.');try {isDispatching = true;state = reducer(state, action);} finally {isDispatching = false;}final List<_VoidCallback> _notifyListeners = listeners.toList(growable: false,);for (_VoidCallback listener in _notifyListeners) {listener();}notifyController.add(state);};

    store的dispatch過程比較簡單,主要就是進行reducer的調(diào)用,處理完成后通知監(jiān)聽者。

    3.middleware

    Page繼承自Component,增加了middleware機制,fish-redux的redux部分本身其實就對middleware做了支持,可以通過StoreEnhancer的方式將middlewares進行組裝,合并到Store的dispatch函數(shù)中。

    middleware機制可以允許我們通過中間件的方式對redux的state做AOP處理,比如fish-redux自帶的logMiddleware,可以對state的變化進行l(wèi)og,分別打印出state變化前和變化后的值。

    當(dāng)Page配置了middleware之后,在創(chuàng)建pageStore的過程中會將配置的middleware傳入,傳入之后會對store的dispath進行增強加工,將middleware的處理函數(shù)串聯(lián)到dispatch中。

    // redux_component/component.dartWidget buildPage(P param) {return wrapper(_PageWidget<T>(component: this,storeBuilder: () => createPageStore<T>(initState(param),reducer,applyMiddleware<T>(buildMiddleware(middleware)),),));} // redux_component/page_store.dartPageStore<T> createPageStore<T>(T preloadedState, Reducer<T> reducer,[StoreEnhancer<T> enhancer]) =>_PageStore<T>(createStore(preloadedState, reducer, enhancer)); // redux/create_store.dartStore<T> createStore<T>(T preloadedState, Reducer<T> reducer,[StoreEnhancer<T> enhancer]) =>enhancer != null? enhancer(_createStore)(preloadedState, reducer): _createStore(preloadedState, reducer);

    所以這里可以看到,當(dāng)傳入enhancer時,createStore的工作被enhancer代理了,會返回一個經(jīng)過enhancer處理過的store。而PageStore創(chuàng)建的時候傳入的是中間件的enhancer。

    // redux/apply_middleware.dartStoreEnhancer<T> applyMiddleware<T>(List<Middleware<T>> middleware) {return middleware == null || middleware.isEmpty? null: (StoreCreator<T> creator) => (T initState, Reducer<T> reducer) {assert(middleware != null && middleware.isNotEmpty);final Store<T> store = creator(initState, reducer);final Dispatch initialValue = store.dispatch;store.dispatch = (Action action) {throw Exception('Dispatching while constructing your middleware is not allowed. ''Other middleware would not be applied to this dispatch.');};store.dispatch = middleware.map((Middleware<T> middleware) => middleware(dispatch: (Action action) => store.dispatch(action),getState: store.getState,)).fold(initialValue,(Dispatch previousValue,Dispatch Function(Dispatch) element) =>element(previousValue),);return store;}; }

    這里的邏輯其實就是將所有的middleware的處理函數(shù)都串到store的dispatch,這樣當(dāng)store進行dispatch的時候所有的中間件的處理函數(shù)也會被調(diào)用。
    下面為各個處理函數(shù)的執(zhí)行順序,

    首先還是component中的dispatch D1 會被執(zhí)行,然后傳遞給store的dispatch,而此時store的dispatch已經(jīng)經(jīng)過中間件的增強,所以會執(zhí)行中間件的處理函數(shù),最終store的原始dispatch函數(shù)D2會被執(zhí)行。

    三.總結(jié)

    通過上面的內(nèi)容,現(xiàn)在我們可以知道一個action是如何一步步的派送給effect,reducer去進行處理的,我們也可以通過middleware的方式去跟蹤state的變化,這樣的擴展性給框架本身帶來無限可能。

    原文鏈接
    本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。

    總結(jié)

    以上是生活随笔為你收集整理的Fish Redux中的Dispatch是怎么实现的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。