一統天下 flutter - widget 狀態管理: 狀態管理 - Redux

源碼 https://github.com/webabcd/flutter_demo
作者 webabcd

一統天下 flutter - widget 狀態管理: 狀態管理 - Redux

示例如下:

lib\state\redux.dart

/*
 * 狀態管理 - Redux
 *
 * Redux 是單向數據流,更新數據後,所有監聽者都可以收到更新事件並獲取更新後的數據
 *
 * 流程:
 * 1、View 生成 Action(類型和數據)
 * 2、Store 將 Action 派發給 Reducer
 * 3、Reducer 根據 Action 的類型和數據做邏輯處理,處理結果保存在 State 中,然後把 State 保存到 Store 中
 * 4、所有監聽了此 Store 的 View 都會收到更新事件,並可以獲取到這個 Store
 * 總結一下就是 View -> Action -> Reducer -> Store -> View
 *
 *
 * 在 pubspec.yaml 中做如下配置,然後 flutter pub get
 * dependencies:
 *   redux: ^5.0.0
 *   flutter_redux: ^0.10.0
 */

import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

import '../helper.dart';

class ReduxDemo extends StatefulWidget {
  const ReduxDemo({Key? key}) : super(key: key);

  @override
  _ReduxDemoState createState() => _ReduxDemoState();
}

class _ReduxDemoState extends State<ReduxDemo> {

  /// Store
  /// 實例化 Store 時需要指定其關聯的 Reducer 以及初始的 State 數據
  final _store = Store<_InfoState>(infoReducer, initialState: _InfoState(messageList: []));

  final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    /// StoreProvider 用於爲其所有的後代監聽指定的 Store
    return StoreProvider(
      /// 需要監聽的 Store
      store: _store,
      child: Scaffold(
        appBar: AppBar(title: const Text("title"),),
        backgroundColor: Colors.orange,
        body: Center(
          /// 監聽的 Store 更新時
          /// 以本例來說,_InfoState 是 Store 中保存的 State 的類型,List<Widget>? 是 converter 處理後的數據類型
          child: StoreConnector<_InfoState, List<Widget>?>(
            /// 通過 converter 處理數據,並返回指定類型的結果
            converter: (store) {
              return [for (var i = 0; i < store.state.messageList.length; i++) MyText(store.state.messageList[i])];
            },
            /// 根據 converter 後的結果,渲染指定的 Widget
            /// 以本例來說,items 是 converter 處理後的 List<Widget>? 類型的數據
            builder: (context, items) {
              return ListView.builder(
                itemBuilder: (context, index) => items![index],
                itemCount: items?.length,
              );
            },
          ),
        ),
        floatingActionButton: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            FloatingActionButton(
              heroTag: 0,
              child: const Icon(Icons.remove),
              onPressed: () {
                /// 將 Action 派發給 Reducer
                _store.dispatch(RemoveMessageAction());
              },
            ),
            FloatingActionButton(
              heroTag: 1,
              child: const Icon(Icons.add),
              onPressed: () async{
                var result = await showDialog<String>(
                  barrierDismissible: false,
                  context: context,
                  builder: (BuildContext context) => AlertDialog(
                    content: TextField(controller: _controller,),
                    actions: [
                      TextButton(
                        onPressed: () => Navigator.pop(context, _controller.text),
                        child: const Text('確認'),
                      ),
                    ],
                  ),
                );
                if (result?.isNotEmpty ?? false) {
                  /// 將 Action 派發給 Reducer
                  _store.dispatch(AddMessageAction(_controller.text));
                  _controller.text = "";
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

/// State
class _InfoState {
  List<String> messageList;
  _InfoState({required this.messageList});
}

/// Action
class AddMessageAction {
  final String message;
  AddMessageAction(this.message);
}
class RemoveMessageAction {}

/// Reducer
_InfoState infoReducer(_InfoState state, dynamic action) {
  if (action.runtimeType == AddMessageAction) {           /// 判斷 Action 的類型
    var message = (action as AddMessageAction).message;   /// 獲取 Action 的數據
    state.messageList.add(message);
    return state;
  }
  if (action.runtimeType == RemoveMessageAction) {
    if (state.messageList.isNotEmpty) {
      state.messageList.removeAt(0);
    }
    return state;
  }
  return state;
}

源碼 https://github.com/webabcd/flutter_demo
作者 webabcd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章