redux 及在Android上應用 rekotlin

什么是redux

redux 的概念來源于前端,是一個“可預測的狀態(tài)容器”,采用“單向數(shù)據(jù)流”的思想,目的是為了讓JS的狀態(tài)管理變得更加可預期。

為什么使用redux

redux 存在的目的是為了解決組件之間的通信以及集中保存管理項目的狀態(tài)松靡。隨著項目變得越來越大,組件之間的通信越來越復雜建椰,狀態(tài)越來越多雕欺,項目就變得難以維護。
使用redux管理狀態(tài),是將所有狀態(tài)都保存在store中屠列,各組件可以直接從store中獲取到自己需要的狀態(tài)啦逆。這樣將全局狀態(tài)保存到一處統(tǒng)一管理,使項目更加容易維護笛洛,組件之間的通信更加清晰夏志。

不使用Redux和使用Redux時父子組件之間的通信方式
  • 沒有使用Redux的情況,如果兩個組件(非父子關系)之間需要通信的話苛让,可能需要多個中間組件為他們進行消息傳遞沟蔑,這樣既浪費了資源,代碼也會比較復雜狱杰。
  • Redux中提出了單一數(shù)據(jù)源Store用來存儲狀態(tài)數(shù)據(jù)瘦材,所有的組件都可以通過Action修改Store,也可以從Store中獲取最新狀態(tài)仿畸,使用redux可以完美解決組件之間的通信問題食棕。

4 張動圖解釋為什么(什么時候)使用 Redux

redux的核心概念及rekotlin的應用

redux的工作流程


rekotlin的工作流程

Store

  • Store可以看作一個狀態(tài)容器,一個應用只能有一個Store颁湖。Store提供一些方法用于存取狀態(tài)宣蠕,分發(fā)狀態(tài)及注冊監(jiān)聽例隆。以下是rekotlin中對于Store的接口定義中的幾個常用方法
interface StoreType<State: StateType>: DispatchingStoreType {

    /**
     * 當前Store中存儲的State
     */
    val state: State

    /**
     * 所有方便的 `dispatch` 方法使用的主要調度函數(shù)甥捺。
     * 這個調度功能可以通過提供中間件來擴展。
     * typealias DispatchFunction = (Action) -> Unit
     */
    var dispatchFunction: DispatchFunction

    /**
     * 將訂閱者注冊到Store镀层,當Store中的State發(fā)生改變時镰禾,訂閱者的`newState`方法將被調用
     */
    fun <S: StoreSubscriber<State>> subscribe(subscriber: S)

    /**
     * 解注冊訂閱者,State更新時訂閱者將不再收到通知
     */
    fun <SelectedState> unsubscribe(subscriber: StoreSubscriber<SelectedState>)

    /**
     * 分發(fā)一個Action用于修改Store中的State
     *(這是DispatchingStoreType中定義的方法)
     */
    fun dispatch(action: Action)
    
    ···
}

State

  • State代表狀態(tài)唱逢,是某個時刻表示一個View渲染所需所有數(shù)據(jù)狀態(tài)的集合吴侦,實際上是一個狀態(tài)樹。
    Redux 規(guī)定坞古,一個 State 對應一個 View备韧。只要 State 相同,View 就相同痪枫。你知道 State织堂,就知道 View 是什么樣,反之亦然奶陈。
interface StateType

data class ViewState(
    // 表示當前State對應的View中渲染所需內容
    val isVisible: Boolean = true,
    val titleText: String = "title",
    // 表示子View對應的State易阳,形成一個狀態(tài)樹
    val statusLayerState: StatusLayerState? = null,
    val businessLayerState: BusinessLayerState? = null
) : StateType

kotlin中使用data class表示State,方便進行copy()操作

Action

  • State 的變化吃粒,會導致 View 的變化潦俺。但是,用戶接觸不到 State,只能接觸到 View事示。所以早像,State 的變化必須是 View 導致的。Action 就是 View 發(fā)出的通知肖爵,表示 State 應該要發(fā)生變化了扎酷。
/**
 * 所有被分發(fā)的Action都需要實現(xiàn)這個接口
 */
interface Action

class ViewVisibleAction(val isVisible: Boolean) : Action

Reducer

  • Store 收到 Action 以后,必須給出一個新的 State遏匆,這樣 View 才會發(fā)生變化法挨。這種 State 的計算過程就叫做 Reducer。
  • Reducer 是一個純函數(shù)幅聘,它接收 Action 和當前 State 作為參數(shù)凡纳,返回一個新的 State。
fun viewReducer(action: Action, viewState: ViewState?): ViewState {
      var newState = viewState ?: viewState()
      when(action) {
            is ViewVisibleAction -> {
                  newState = newState.copy(isVisible = action.isVisible)
            }
      }
      newState = newState.copy(statusLayerState = statusLayerReducer(action, viewState?.statusLayerState))
      newState = newState.copy(businessLayerState = businessLayerReducer(action, viewState?.businessLayerState))
      return newState
}

fun statusLayerReducer(action: Action, statusLayerState: StatusLayerState?): StatusLayerState {
      ···
}

fun businessLayerReducer(action: Action, businessLayerState: BusinessLayerState?): BusinessLayerState {
      ···
}

Reducer 函數(shù)最重要的特征是帝蒿,它是一個純函數(shù)荐糜。也就是說,只要是同樣的輸入葛超,必定得到同樣的輸出暴氏。
由于 Reducer 是純函數(shù),就可以保證同樣的State绣张,必定得到同樣的 View答渔,任何時候,與某個 View 對應的 State 總是一個不變的對象侥涵。但也正因為這一點沼撕,Reducer 函數(shù)里面不能改變 State,必須返回一個全新的對象芜飘。因而State最好是只讀的务豺。

高階用法 Middleware

  • Middleware中間件,在store.dispatch()分發(fā)Action到Reducer之間被調用嗦明,常用于添加笼沥、改造功能。


// typealias別名娶牌,僅做內聯(lián)替換奔浅,不生成新的函數(shù)
typealias DispatchFunction = (Action) -> Unit
typealias Middleware<State> = (DispatchFunction, () -> State?) -> (DispatchFunction) -> DispatchFunction

class viewMiddleware(): Middleware<ViewState> {
    override fun invoke(
        p1: DispatchFunction,
        p2: () -> ViewState?
    ): (DispatchFunction) -> DispatchFunction {
        return fun(next: DispatchFunction): (Action) -> Unit {
            return fun(action: Action) {
                next(action)
            }
        }
    }
}

Store中dispatchFunction的實現(xiàn)

    override var dispatchFunction: DispatchFunction = middleware
            .reversed()
            .fold({ action: Action -> this._defaultDispatch(action) }, { dispatchFunction, middleware ->
                val dispatch = { action: Action -> this.dispatch(action) }
                val getState = { this._state }
                middleware(dispatch, getState)(dispatchFunction)
            })

redux的三大原則

  • Single source of truth 單一數(shù)據(jù)源
    • The global state of your application is stored in an object tree within a single store. 應用的全局狀態(tài)以樹的形式存儲在單一store中
  • State is read-only 狀態(tài)只讀
    • The only way to change the state is to emit an action, an object describing what happened. 唯一改變state的方式是發(fā)送一個表示發(fā)生了什么的action
  • Changes are made with pure functions 變化由純函數(shù)計算
    • To specify how the state tree is transformed by actions, you write pure reducers. 編寫純函數(shù)去通過actions計算state發(fā)生了什么變化

redux使用場景

“如果你不知道是否需要 Redux,那就是不需要它裙戏〕送梗”

  • 如果你的UI層非常簡單,沒有很多互動累榜,redux 就是不必要的营勤,用了反而增加復雜性灵嫌。在應用程序增長到管理狀態(tài)變得麻煩的規(guī)模的情況下,可以使用redux葛作,使狀態(tài)管理和溯源變得容易和簡單寿羞。所以總體原則是能不用就不用, 實在干不動了再用。
  • 某個組件的狀態(tài)赂蠢,需要共享绪穆。
  • 某個狀態(tài)需要在任何地方都可以拿到。
  • 一個組件需要改變全局狀態(tài)虱岂。
  • 一個組件需要改變另一個組件的狀態(tài)玖院。

使用redux的優(yōu)勢

狀態(tài)可預測:相同的State和Action傳遞給Reducer,輸出的結果總是相同的(純函數(shù)特性)第岖。且當你需要修改狀態(tài)時难菌,必須重新開始走一個修改的流程,這種限制狀態(tài)修改的方式蔑滓,讓狀態(tài)變得可預測郊酒,容易調試。
可維護性:具有 Redux 知識的人更容易理解任何 Redux 應用程序的結構键袱,且有助于用戶將業(yè)務邏輯與組件樹分離燎窘。
單向數(shù)據(jù)流:所有狀態(tài)的改變可記錄、可跟蹤蹄咖,源頭易追溯褐健,數(shù)據(jù)具有唯一出口和入口,使得數(shù)據(jù)操作更直觀更容易理解比藻。

引申

單向數(shù)據(jù)流和雙向綁定的優(yōu)缺點對比

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末铝量,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子银亲,更是在濱河造成了極大的恐慌,老刑警劉巖纽匙,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件务蝠,死亡現(xiàn)場離奇詭異,居然都是意外死亡烛缔,警方通過查閱死者的電腦和手機馏段,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來践瓷,“玉大人院喜,你說我怎么就攤上這事≡未洌” “怎么了喷舀?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵砍濒,是天一觀的道長。 經(jīng)常有香客問我硫麻,道長爸邢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任拿愧,我火速辦了婚禮杠河,結果婚禮上,老公的妹妹穿的比我還像新娘浇辜。我一直安慰自己券敌,他們只是感情好,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布柳洋。 她就那樣靜靜地躺著陪白,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膳灶。 梳的紋絲不亂的頭發(fā)上咱士,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機與錄音轧钓,去河邊找鬼序厉。 笑死,一個胖子當著我的面吹牛毕箍,可吹牛的內容都是我干的弛房。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼而柑,長吁一口氣:“原來是場噩夢啊……” “哼文捶!你這毒婦竟也來了?” 一聲冷哼從身側響起媒咳,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤粹排,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涩澡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顽耳,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年妙同,在試婚紗的時候發(fā)現(xiàn)自己被綠了射富。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡粥帚,死狀恐怖胰耗,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情芒涡,我是刑警寧澤柴灯,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布卖漫,位于F島的核電站,受9級特大地震影響弛槐,放射性物質發(fā)生泄漏懊亡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一乎串、第九天 我趴在偏房一處隱蔽的房頂上張望店枣。 院中可真熱鬧,春花似錦叹誉、人聲如沸鸯两。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钧唐。三九已至,卻和暖如春匠襟,著一層夾襖步出監(jiān)牢的瞬間钝侠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工酸舍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留帅韧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓啃勉,卻偏偏與公主長得像忽舟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淮阐,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內容