皖林 2020-03-03
参考QF.UIWidgets
参考Unity官方示例 - ConnectAppCN
前面说过,当时没想明白一个问题,在reducer中每次返回一个new State()
, 会造成极大浪费,没想到用什么办法来解决。
然后发现这些示例里面并没有每次创建一个新的State,只是直接修改了相应的值……那这样就简单多了。把Redux结构划分为不同数据模块,更方面管理。
在这里从头做一个简单的demo,包含两个页面:“homepage”,显示一条信息, “newpage”,显示一个计数
// Main.cs using System.Collections.Generic; using Unity.UIWidgets; using Unity.UIWidgets.engine; using Unity.UIWidgets.material; using Unity.UIWidgets.Redux; using Unity.UIWidgets.widgets; using UnityEngine; using Redux.State; using Redux.Reducer; using Redux.View; namespace Redux { public class Main : UIWidgetsPanel { protected override void OnEnable() { base.OnEnable(); } protected override Widget createWidget() { var widget = new MaterialApp( initialRoute: "/", routes: new Dictionary<string, WidgetBuilder>() { { "/", context => new HomePage() }, { "new", context => new NewPage() }, } ); var store = new Store<AppState>( reducer: AppReducer.Reduce, initialState: new AppState() ); return new StoreProvider<AppState>( child: widget, store: store ); } } }
// View/HomePage.cs // 因为这里不是重点,NewPage略 using System; using System.Collections.Generic; using Unity.UIWidgets.materal; using Unity.UIWidgets.painting; using Unity.UIWidgets.Redux; using Unity.UIWidgets.widgets; using UnityEngine; namespace Redux.View { public class HomePage : StatelessWidget { var widget = new Scaffold( appBar: new appBar( title: new Text("Home") ), body: new Center( children: new List<Widget> { new StoreConnector<AppState, string>( converter: (state) => state.globalState.message, builder: (context1, text, dispatcher) => new Text(text) ), new StoreConnector<AppState, object>( converter: (state) => null, builder: (context2, _, dispatcher) => new RaisedButton( child: new Text("当前时间"), onPressed: () => { dispatcher.dispatch(new Action.Global.SetMessageAction { message = DateTime.Now.ToString() }); } ) ), new RaisedButton( child: new Text("打开新页面"), onPressed: () => { Navigator.pushNamed(context, "new"); } ) } ) ); return widget; } }
// State/AppState.cs namespace Redux.State { public class AppState { public BagState bagState; public GlobalState globalState; public static AppState GetState() { AppState = new AppState { bagState = new BagState { itemCount = 0; }, globalState = new GlobalState { message = "hello", }, } } } } // State/BagState.cs namespace Redux.State { public class BagState { public int itemCount; } } // State/GlobalState.cs namespace Redux.State { public class GlobalState { public string message; } }
// Action/BagAction.cs namespace Redux.Action { public interface IBagAction {} } namespace Redux.Action.Bag { public class AddCountAction : IBagAction { public int count; } public class RemoveCountAction : IBagAction { public int count; } } // Action/GlobalAction.cs namespace Redux.Action { public interface IGlobalAction {} } namespace Redux.Action.Global { public class SetMessageAction : IGlobalAction { public string message; } }
// Reducer/AppReducer.cs using Redux.Action; using Redux.State; namespace Redux.Reducer { public static class AppReducer { public static AppState Reduce(AppState state, object action) { switch (action) { case IBagAction bagAction: return BagReducer.Reduce(state, bagAction); case IGlobalAction globalAction: return GlobalReducer.Reduce(state, globalAction); default: return state; } } } } // Reducer/BagReducer.cs using Redux.Action; using Redux.Action.Bag; using Redux.State; namespace Redux.Reducer { public static class BagReducer { public static AppState Reduce(AppState state, IBagAction action) { switch (action) { case AddCountAction addCountAction: return OnAddCountAction(state, addCountAction); case RemoveCountAction removeCountAction: return OnRemoveCountAction(state, removeCountAction); default: return state; } } private static AppState OnAddCountAction(AppState state, AddCountAction action) { state.bagState.itemCount += action.count; return state; } private static AppState OnRemoveCountAction(AppState state, RemoveCountAction action) { state.bagState.itemCount -= action.count; return state; } } } // Reducer/GlobalReducer.cs using Redux.Action; using Redux.Action.Global; using Redux.State; namespace Redux.Reducer { public static class GlobalReducer { public static AppState Reduce(AppState state, IGlobalAction action) { switch (action) { case SetMessageAction setMessageAction: return OnSetMessageAction(state, setMessageAction); default: return state; } } private static AppState OnSetMessageAction(AppState state, SetMessageAction action) { state.globalState.message = action.message; return state; } } }
按这样的模式,redux部分(仅此部分)可以考虑写相应的代码生成工具了