React 生態裡廣為人知的 Redux 狀態管理,其實在 Flutter 中也能適用,它能很好的處理單一資料和狀態共享,在一定程度上對於分割專案之間複雜的業務有一定的積極作用,可閱讀可維護也能做的很不錯。對於使用過 React 的前端開發來說 Redux 的概念肯定熟記於心了,不過我還是要簡單說一些東西,只有這樣我們才能更好的進入下一個環節。

Redux 主要由三個部分組成:Store,Action,Reducer

Action 用於定義資料變化的行為(至少在語義上我們應該定義明確的行為)

Reducer 用於根據 Action 來產生新的狀態

Store 用於儲存和管理 state

在 Flutter 使用 Redux 來共享狀態和管理單一資料

這個專案的 Redux 例子使用瞭如下兩個 package:

https://

github。com/brianegan/fl

utter_redux

https://

github。com/brianegan/fl

utter_redux_dev_tools

讓我們先來看一看具體的效果圖:

在 Flutter 使用 Redux 來共享狀態和管理單一資料

根據效果來分析我們的 Store 至少是一個數組,數組裡面是一個物件,這個物件至少有兩個屬性分別是 name 和 icon,那麼我們應該先來定義全域性的 state 和 這個物件。

// 全域性 state

class

AppState

{

List

<

AVList

>

data

AppState

this

data

);

}

import

‘package:flutter/material。dart’

// 具體使用的物件

class

AVList

{

final

String

name

final

IconData

icon

AVList

this

name

this

icon

);

AVList

fromJSON

Map

<

String

dynamic

>

json

name

=

json

‘name’

],

icon

=

json

‘icon’

];

}

你能看見它們分別做了兩件事情,往ListView中新增一個Item,將最後一個Item從ListView中刪除,那麼接下來我們要定義它們的Action和Reducer。

// Action

import

‘package:my_flutter_app/flow/listModel。dart’

List

<

AVList

>

addItem

List

<

AVList

>

avLists

action

){

avLists

add

action

avLists

0

]);

return

avLists

}

List

<

AVList

>

removeItem

List

<

AVList

>

avLists

action

){

avLists

removeLast

();

return

avLists

}

import

‘package:redux/redux。dart’

import

‘package:my_flutter_app/flow/listModel。dart’

import

‘package:my_flutter_app/flow/listActions。dart’

final

ListReducer

=

combineReducers

<

List

<

AVList

>>

([

TypedReducer

<

List

<

AVList

>

AddAVListAction

>

addItem

),

TypedReducer

<

List

<

AVList

>

RemoveAVListAction

>

removeItem

]);

class

AddAVListAction

{

final

List

<

AVList

>

avLists

AddAVListAction

this

avLists

);

}

class

RemoveAVListAction

{}

我們可以使用 combineReducers 來註冊你的 Action,並且使用 TypedReducer 來對映你的 Action。

現在,我們可以在

main。dart

中定義你全域性的 Store 和 Reducer :

AppState

appReducer

AppState

state

action

{

return

new

AppState

ListReducer

state

data

action

);

}

final

store

=

new

Store

<

AppState

>

appReducer

initialState:

new

AppState

([

new

AVList

“android”

Icons

android

)])

);

之前我們定義的資料結構中是一個List,其中物件的型別是AVList,因為我們可以在初始化的時候給它一個

預設值

接下來我們可以來完善 Widget 這一層,在這一層中基本上我們需要做:

Widget 繫結 Store 中的 state

Widget 觸發某個 Action

Reducer 根據某個 Action 觸發更新 state

更新 Store 中 state 繫結的 Widget

在這裡我們會使用到幾個 Widget 和一個 Dispatch 來完成上述的步驟,第一步我們要使用 StoreProvider 它會將繫結的 Store 傳遞給它的所有子 Widget ,其次我們需要使用 StoreConnector 它會將更新後的資料 callback 給你,最後我們會使用 dispatch 來執行某些 Action ,完成某些 state 的操作。

完整的例子:

import

‘package:flutter/material。dart’

import

‘package:redux/redux。dart’

import

‘package:flutter_redux/flutter_redux。dart’

import

‘package:my_flutter_app/flow/listModel。dart’

import

‘package:my_flutter_app/flow/listReducer。dart’

class

AppState

{

List

<

AVList

>

data

AppState

this

data

);

}

AppState

appReducer

AppState

state

action

{

return

new

AppState

ListReducer

state

data

action

);

}

class

AVReduxList

extends

StatelessWidget

{

final

Store

<

AppState

>

store

AVReduxList

({

Key

key

this

store

})

super

key:

key

);

@

override

Widget

build

BuildContext

context

{

return

new

StoreProvider

<

AppState

>

store:

store

child:

new

MaterialApp

home:

new

Scaffold

appBar:

new

AppBar

title:

new

Text

‘AVReduxList’

),

),

body:

new

Column

children:

<

Widget

>

new

StoreConnector

<

AppState

List

<

AVList

>>

converter:

store

=>

store

state

data

builder:

BuildContext

context

data

){

return

new

Container

height:

500。0

child:

ListView

builder

itemCount:

data

length

itemBuilder:

BuildContext

context

int

position

){

return

new

Padding

padding:

EdgeInsets

all

10。0

),

child:

new

Row

children:

<

Widget

>

new

Text

data

position

]。

name

),

new

Icon

data

position

]。

icon

color:

Colors

blue

],

),

);

},

),

);

},

),

new

Row

crossAxisAlignment:

CrossAxisAlignment

center

children:

<

Widget

>

new

RaisedButton

color:

Colors

blue

child:

new

Text

‘更新’

style:

new

TextStyle

color:

Colors

white

),

),

onPressed:

(){

store

dispatch

new

AddAVListAction

new

AVList

“android”

Icons

android

)]

));

},

),

new

RaisedButton

color:

Colors

blue

child:

new

Text

‘刪除最後一項’

style:

new

TextStyle

color:

Colors

white

),

),

onPressed:

(){

store

dispatch

new

RemoveAVListAction

()

);

},

],

],

),

),

);

}

}

Redux Dev Tools

這是一個類似 Redux Time Travel 的 UI 小工具,在開發階段我們可以使用這個工具來追溯你的操作,因此我們需要重新定義一個

入口檔案

main_dev。dart:

import

‘package:flutter/material。dart’

import

‘package:flutter_redux_dev_tools/flutter_redux_dev_tools。dart’

import

‘package:redux_dev_tools/redux_dev_tools。dart’

import

‘package:my_flutter_app/AVReduxList。dart’

import

‘package:my_flutter_app/flow/listModel。dart’

void

main

(){

final

store

=

new

DevToolsStore

<

AppState

>

appReducer

initialState:

new

AppState

([

new

AVList

“android”

Icons

android

)])

);

runApp

new

ReduxDevToolsContainer

store:

store

child:

new

AVReduxList

store:

store

devDrawerBuilder:

BuildContext

context

){

return

new

Drawer

child:

new

Padding

padding:

new

EdgeInsets

only

top:

24。0

),

child:

new

ReduxDevTools

store

),

),

);

},

),

));

}

在這裡我們需要使用 DevToolsStore 來定義你的全域性 Store ,另外我們還需要對原來的 AVReduxList進行一些改造,增加一個 devDrawerBuilder 屬性來控制 DevTools 的繪製。

// AVReduxList。dart

class

AVReduxList

extends

StatelessWidget

{

final

Store

<

AppState

>

store

final

WidgetBuilder

devDrawerBuilder

AVReduxList

({

Key

key

this

store

this

devDrawerBuilder

})

super

key:

key

);

@

override

Widget

build

BuildContext

context

{

return

new

StoreProvider

<

AppState

>

store:

store

child:

new

MaterialApp

home:

new

Scaffold

endDrawer:

devDrawerBuilder

!=

null

devDrawerBuilder

context

null

。。。

}

}

最後,我們在 VSCode 中重新新增一個新的

啟動項

{

“name”

“Flutter_Redux_DevTools”

“type”

“dart”

“request”

“launch”

“program”

“lib/main_dev。dart”

},

效果圖:

在 Flutter 使用 Redux 來共享狀態和管理單一資料