• <ul id="cgeq2"></ul>
  • 歡迎您光臨深圳塔燈網絡科技有限公司!
    電話圖標 余先生:13699882642

    網站百科

    為您解碼網站建設的點點滴滴

    Flutter 狀態管理

    發表日期:2018-12 文章編輯:小燈 瀏覽次數:3353

    在 React Native 要做狀態管理通常都是使用 Redux,這種方式非常好。幸運的是,在 Flutter 也支持使用 Redux。

    flutter_redux 是一個支持在 Flutter 里使用 Redux 的庫,但并不是使用 JS 版本的 Redux,而是使用 dart_redux,這是一個在 dart 上的 Redux 實現。

    Redux 的基礎知識就不多說了,在這里主要介紹如何在 Flutter 里使用 Redux 管理應用的數據狀態。

    先安裝依賴:

    dependencies: redux: ^3.0.0 flutter_redux: ^0.5.2 

    在 Flutter Redux 里有一個必要知道的概念:

    • StoreProvider - 一個組件,它會將給定的 Redux Store 傳遞給它的所有子組件。
    • StoreBuilder - 一個子 Widget 組件,StoreProvider 它從 Action 中獲取 Store 并將其傳遞給 Widget builder 函數。
    • StoreConnector - 從最近的 StoreProvider 祖先獲取 Store 的子 Widget,使用給定的函數將其轉換 Store 為 Action,并將其傳遞給函數。只要 Store 發出更改事件,Widget 就會自動重建。無需管理訂閱!

    Flutter Redux 的概念就像是 react-redux 一樣。

    下面來看一個簡單的示例。

    import 'package:flutter/material.dart'; import 'package:redux/redux.dart'; import 'package:flutter_redux/flutter_redux.dart';void main() { runApp(new FlutterReduxApp()); }// 定義個 Types 枚舉 enum Types { Increment }// Reducer 處理 int Reducer(int state, action) { if (action == Types.Increment) { return state + 1; }return state; }// 創建一個 Action 類 class Action { dynamic store; dynamic dispatch; Action(store) { this.store = store; this.dispatch = store.dispatch; }// 某個 Action increment() { dispatch(Types.Increment); } }class FlutterReduxApp extends StatelessWidget { // 創建一個 store Action action; final store = new Store(Reducer, initialState: 0);@override Widget build(BuildContext context) { // 初始化 action if (action == null) { action = new Action(store); }return new MaterialApp( // 創建一個 Provider home: new StoreProvider( store: this.store, child: new Scaffold( body: new Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: [ new Text('You have pushed the button this many times:'), // 連接器,連接之后可以獲取數據,在 builder 里渲染內容 new StoreConnector<int, String>( converter: (store) => store.state.toString(), builder: (context, count) => new Text(count), ) ], ), ), floatingActionButton: new FloatingActionButton( onPressed: action.increment, // action child: new Icon(Icons.add), ), ), ), ); } } 

    在需要改變狀態的組件里使用 StoreConnector 連接數據(避免對整個內容做一次性的連接,導致整個渲染)。

    在這里 Store 是一個泛型類,在初始化時請給它一個類型,否則就是 Store<int>。很多時候 State 是一個復雜的結構,并不是一個簡單的 int 類型,那么如何適配?

    // Reducer 處理 State reducer(State state, action) { if (action == Types.Increment) { state.count++; return state.newState(state); }return state; }class State { List<String> list; String name; int count; State(this.list, this.name, this.count); // 返回一個新的實例 newState(State obj) { this.name = obj.name; this.list = obj.list; this.count = obj.count; return new State(obj.list, obj.name, obj.count); } }// 創建一個 store final store = new Store<State>(reducer, initialState: new State([], 'abc', 0));// 連接器,連接之后可以獲取數據,在 builder 里渲染內容 new StoreConnector<State, String>( converter: (store) => store.state.count.toString(), builder: (context, count) => new Text(count), ), 

    StoreConnector 里的 converter 一定要是返回 String 嗎?目前為止是的,因為大多數的在 Widget 上都是使用字符串渲染。

    此外,可以使用 StoreConnector 對某個組件進行數據的連接,對于不變化的組件那就沒必要連接了。

    在 Action 初始了一個 store 和 dispatch,這樣就可以在方法里直接引用 store 和 dispatch。

    // 創建一個 Action 類 class Action { Store<State> store; dynamic dispatch; Action(store) { this.store = store; this.dispatch = store.dispatch; }// 某個 Action increment() { dispatch(Types.Increment); } } 

    中間件

    中間件是一個非常有用的東西,它可以在 Reducer 操作之前做一些攔截或者記錄工作。

    Store 的第三個參數是一個接受中間件的參數,我們可以通過下面的定義中間件方式,為 Store 添加中間件。

    loggingMiddleware<T>(Store<T> store, action, NextDispatcher next) { print('${new DateTime.now()}: $action'); next(action); }final store = new Store<int>( counterReducer, initialState: 0, middleware: [loggingMiddleware], ); 

    異步操作

    在 action 里使用 async 即可,在等待異步操作完成后再調用 dispatch。

    // 某個 Action increment() async { // 模擬某個異步操作 await new Future.delayed(new Duration(seconds: 1)); // 完成后 dispatch dispatch(Types.Increment); } 

    傳遞數據

    在調用 dispatch 的時候 action 是一個 dynamic 類型,在上面是沒有傳遞數據的,而數據的變化在 Reducer 里。

    那么如何傳遞數據呢?在 action 里是一個 dynamic 類型,因此可以把 action 寫成 Map 類型,在 Map 里獲取 type 和 data。

    // Reducer 處理 State reducer(State state, action) { if (action['type'] == Types.Increment) { state.count = action['data']; return state.newState(state); }return state; }// 某個 Action increment() async { // 模擬某個異步操作 await new Future.delayed(new Duration(seconds: 1)); // 完成后 dispatch dispatch({ 'type': Types.Increment, 'data': store.state.count + 1, }); } 

    這樣就可以把數據從 Action 傳遞到 Reducer 了。

    精簡代碼

    在上面的代碼里,在 Action 里得到最新的狀態只,在 Reducer 里又需要進行一次賦值,這樣會多出很多重復的代碼。現在把 Action 變成一個 newState 函數,在函數里更新最新的狀態,在 Reducer 里只創建新的實例即可,這樣可以節省很多代碼,Types 也不需要寫了。

    // Reducer 處理 State reducer(State state, action) { if (action is Function) { var s = state.newState(action(state)); if (s != null) return s; } return state; }// 某個 Action increment() async { // 模擬某個異步操作 await new Future.delayed(new Duration(seconds: 1)); // 完成后 dispatchdispatch((State state) { // 要更新的狀態 state.count++; return state; }); } 

    不知看懂了沒有,實際上就是利用傳遞函數與上下文的特點。


    本頁內容由塔燈網絡科技有限公司通過網絡收集編輯所得,所有資料僅供用戶學習參考,本站不擁有所有權,如您認為本網頁中由涉嫌抄襲的內容,請及時與我們聯系,并提供相關證據,工作人員會在5工作日內聯系您,一經查實,本站立刻刪除侵權內容。本文鏈接:http://www.juherenli.com/17631.html
    相關APP開發
     八年  行業經驗

    多一份參考,總有益處

    聯系深圳網站公司塔燈網絡,免費獲得網站建設方案及報價

    咨詢相關問題或預約面談,可以通過以下方式與我們聯系

    業務熱線:余經理:13699882642

    Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.    

    久久精品丝袜高跟鞋| 亚洲精品天堂成人片?V在线播放| 久久久精品国产亚洲成人满18免费网站| 亚洲国产精品日韩在线| 中文国产成人精品久久一区 | 国产精品熟女福利久久AV| 久久精品国产四虎| 久久福利青草精品资源站| 国产大片51精品免费观看| 亚洲精品在线免费看| 亚洲精品白浆高清久久久久久| 日韩精品无码成人专区| 国产精品久久久久久久久鸭| 亚洲线精品一区二区三区| 无码精品人妻一区二区三区免费 | 一区二区三区日韩精品| 国产精品一区二区久久精品无码| 久久精品视频在线看99| 精品久久久久久亚洲精品| 女人香蕉久久**毛片精品| 国产精品 综合 第五页| 午夜精品视频任你躁| 精品久久无码中文字幕| 久久久久无码精品亚洲日韩| 中文国产成人精品久久96| 加勒比精品久久一区二区三区| 中文字幕精品一区二区| 91精品国产91久久久久久最新| 国产色无码精品视频免费| 任我爽精品视频在线播放| 少妇人妻精品一区二区| 无码人妻精品一区二区三区蜜桃| 亚洲国语精品自产拍在线观看| 亚洲精品自产拍在线观看| 久久久久国产精品麻豆AR影院| 国产成人精品午夜在线播放| 色欲AV永久无码精品无码| 国产成人愉拍精品| 91久久精品一区二区| 99精品视频免费在线观看| 蜜臀久久99精品久久久久久小说|