Unity - UIWidgets 7. Redux接入(二) 把Redux划分为不同数据模块

参考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部分

// 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部分

// 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部分

// 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部分

// 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部分(仅此部分)可以考虑写相应的代码生成工具了

相关推荐