重写Android原生代码中的StateMachine状态拓扑,由树状改为网状

文章介绍了一种针对Android原生状态机的改造,创建了一个支持网状拓扑的状态机实现。作者简化了原生状态机的复杂性,仅保留了必要的功能,包括状态的添加、初始化、状态转移等。同时,文章提供了具体的用例,展示了如何处理不同状态间的转换,如初始化、连接、断开和同步状态。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

使用Android原生状态机,其结构为树状拓扑,不满足需求,需要的状态拓扑是一个网状拓扑。
因此,自己根据原生Android StateMachine.java修改其状态拓扑,
简化了大部分的内容,只保留了自己需要的方法。

一、源码

import android.content.Context;
import android.os.CpuUsageProto;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import com.android.internal.util.State;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ZzhFSM {

    private static final String TAG = "ZzhFsm";
    private HandlerThread mSmThread;
    private SmHandler mSmHandler;
    private String mName;

    /**
     * 初始化状态机,主要是创建一个用于通讯的线程
     * */
    private void initStateMachine(Context context, String name, Looper looper) {
        mName = name;
        mSmHandler = new SmHandler(looper, context, this);
    }

    /**
     * 构造
     * */
    public ZzhFSM(Context context, String name) {
        mSmThread = new HandlerThread(name);
        mSmThread.start();
        Looper looper = mSmThread.getLooper();
        initStateMachine(context, name, looper);
    }

    /**
     * 发送信息给其他线程
     * */
    public void sendMessage(int what) {
        // mSmHandler can be null if the state machine has quit.
        SmHandler smh = mSmHandler;
        if (smh == null) return;
        Message msg = new Message();
        msg.what = what;
        smh.sendMessage(Message.obtain(msg));
    }
    /**
     * 发送信息给其他线程
     * */
    public void sendMessage(Message msg) {
        // mSmHandler can be null if the state machine has quit.
        SmHandler smh = mSmHandler;
        if (smh == null) return;
        Log.d(TAG,"msg.waht = " + msg.what + ", arg1 = " + msg.arg1);
        smh.sendMessage(Message.obtain(msg));
    }
    /**
     * 每个状态都会存储信息
     * */
    public static class StateInfo{
        State state;
        StateInfo[] parentsStateInfo = new StateInfo[10];
        int parentsCount;
        boolean active;
    }

    /**
     * 创建线程,用于线程间通讯
     * */
    private static class SmHandler extends Handler{
        private WeakReference<Context> weakReference;
        private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();
        private State currentState = null;
        private State previousState = null;
        private State initState = null;
        private ZzhFSM mSm;
        private boolean mDbg = true;

        private SmHandler(Looper looper, Context context, ZzhFSM sm) {
            super(looper);
            this.mSm = sm;
            this.weakReference = new WeakReference(context);
        }

        @Override
        public void handleMessage(Message msg) {
            Context context = weakReference.get();
            if (null != context) {
                //仅会对当前的State发送消息
                if (mDbg) Log.d(TAG, "msg.what = " + msg.what);
                StateInfo curStateInfo = mStateInfo.get(getCurrentState());
                if(curStateInfo != null){
                    if (mDbg) Log.d(TAG,"processMsg: " + curStateInfo.state.getName()
                            + ", msg.what = " + msg.what
                            + ", msg.arg1 = " + msg.arg1);
                    curStateInfo.state.processMessage(msg);
                }else {
                    if (mDbg) Log.d(TAG,"curStateInfo:" + curStateInfo.state.getName() + " is null!!!");
                }
            }
        }

        /**
         * 增加状态并将构建状态关系(网状拓扑)(原生的StateMachine是树状拓扑)
         * state:子状态    parent:父状态
         * return:子状态信息
         * */
        private StateInfo addState(State state, State parent){

            //获取的state信息是null,说明hashmap中没有这个state
            StateInfo stateInfo = mStateInfo.get(state);
            if(stateInfo == null) {
                if (mDbg) Log.d(TAG,"stateInfo == null, state = " + state.getName());
                stateInfo = new StateInfo();
                mStateInfo.put(state, stateInfo);
                stateInfo.state = state;
                stateInfo.parentsCount = 0;
                stateInfo.active = false;
            }else {
                if (mDbg) Log.d(TAG,"stateInfo != null, state = " + state.getName());
                stateInfo.parentsCount = stateInfo.parentsCount + 1;
            }

            //判断parent state是否为null
            StateInfo parentStateInfo = null;
            if(parent != null){
                if (mDbg) Log.d(TAG,"parent != null");
                parentStateInfo  = mStateInfo.get(parent);
                if (mDbg) Log.d(TAG,"parentStateInfo.state = " + parentStateInfo.state.getName());
                if(parentStateInfo == null){
                    if (mDbg) Log.d(TAG,"parentStateInfo == null");
                    parentStateInfo = addState(parent, null);
                }else {
                    if (mDbg) Log.d(TAG,"parentStateInfo != null");
                    stateInfo.parentsStateInfo[stateInfo.parentsCount] = parentStateInfo;
                }
            }
            if (mDbg) Log.d(TAG,"---------------addState------------------------");
            return stateInfo;
        }

        /**
         * 设置初始化状态
         * */
        private int setInitialState(State initState){
            this.initState = initState;
            currentState = initState;
            previousState = initState;
            StateInfo stateInfo = mStateInfo.get(initState);
            stateInfo.active = true;
            mStateInfo.put(initState, stateInfo);
            return 0;
        }

        /**
         * 获取当前状态
         * */
        private State getCurrentState(){
            return currentState;
        }

        /**
         * 获取上一个状态
         * */
        private State getPreviousState(){ return previousState; }

        /**
         * 状态转移
         * */
        private int transitionTo(State DesState){
            State mCurrentState = getCurrentState();
            StateInfo desStateInfo = mStateInfo.get(DesState);
            for (StateInfo parentStateInfo : desStateInfo.parentsStateInfo) {
                if(parentStateInfo.state.getName().equals(mCurrentState.getName())){
                    //旧的state执行exit
                    previousState = mCurrentState;
                    mCurrentState.exit();
                    parentStateInfo.active = false;
                    //新的state执行enter
                    currentState = desStateInfo.state;
                    currentState.enter();
                    desStateInfo.active = true;
                    //将它们的active进行保存
                    mStateInfo.put(desStateInfo.state, desStateInfo);
                    mStateInfo.put(parentStateInfo.state, parentStateInfo);
                    break;
                }
            }
            if(mCurrentState.getName().equals(getCurrentState().getName())){
                throw new RuntimeException("illegal destination state:" + DesState.getName()
                        + "is not son state of currentState:" + currentState.getName());
            }
            return 0;
        }

        /**
         * 启动状态机
         * */
        private int start(){
            getCurrentState().enter();
            return 0;
        }

        /**
         * 获取状态hash
         * */
        private HashMap<State, StateInfo> getStateInfoHashMap(){
            return mStateInfo;
        }

    }

    /**
     * SmHandler外部接口:增加状态并将构建状态关系(网状拓扑)
     * */
    public int addState(State state, State parent){
        mSmHandler.addState(state, parent);
        return 0;
    }

    /**
     * SmHandler外部接口:设置初始化状态
     * */
    public int setInitialState(State initState){
        mSmHandler.setInitialState(initState);
        return 0;
    }

    /**
     * SmHandler外部接口:状态转移
     * */
    public int transitionTo(State DesState){
        mSmHandler.transitionTo(DesState);
        return 0;
    }

    /**
     * SmHandler外部接口:获取状态hash
     * */
    public HashMap<State, StateInfo> getStateInfoHashMap(){
        return mSmHandler.getStateInfoHashMap();
    }

    /**
     * SmHandler外部接口:获取当前状态
     * */
    public State getCurrentState(){
        return mSmHandler.getCurrentState();
    }

    /**
     * SmHandler外部接口:获取上一个状态
     * */
    public State getPreviousState(){
        return mSmHandler.getPreviousState();
    }

    /**
     * SmHandler外部接口:启动状态机
     * */
    public int start(){
        mSmHandler.start();
        return 0;
    }

    protected void onHalting() {
    }
}

二、状态拓扑

FsmInitState是初始状态,自动检测是否连接
DisconnectedState是断开状态,本拓扑中,所有状态均可跳到该状态
ConnectedState是连接状态,可以跳到断开状态,断开状态也可以跳到连接状态
DeviceSynchronizedState是同步状态,同步状态代表一个通讯的完成,同步状态可以跳到断开状态。
在这里插入图片描述

三、 具体用例

/***
事件->状态机(当前状态)->当前状态是否有该事件备案
		->没有,忽略
		->有,执行对应Action方法
注意:每次转移状态,都会执行一个状态Action(非事件Action)
所有Action方法均未实现,创建子类,重写即可。
***/
public class Fsm extends ZzhFSM {

    private String TAG = "Fsm";
    public String CurrentFsmName;
    private boolean mDbg = true;
    private ExecutorService executorService;

    /**
     * 设备类型:0x00;
     * */
    public int DeviceType = 0x00;

    /**
     * 设备UID/PID
     * */
    public String DeviceUid;

    /**
     * 连接状态: 已断开 0; 已连接 1; 已同步 2;
     * */
    public int DeviceState = -1;

    /**
     * 是否正在录音: 否 -1; 是 1
     * */
    public int isRecording = 0;

    /***-------------------------EVENT: STATE TRANSITION ACCORDING TO EVENT----------------------------***/

    /**
     * 事件:未定义
     * */
    public static final int EVENT_UNDEFINED = 0;
    /**
     * 事件:发起连接
     * */
    public static final int EVENT_START_CONNECT = 1;
    /**
     * 事件:已连接
     * */
    public static final int EVENT_CONNECTED = 2;
    /**
     * 事件:已断开
     * */
    public static final int EVENT_DISCONNECTED = 3;
    /**
     * 事件:发起设备同步(连接后的设备同步)
     * */
    public static final int EVENT_START_DEVICE_SYNC = 4;
    /**
     * 事件:设备同步成功
     * */
    public static final int EVENT_DEVICES_SYNC_SUCCEED = 5;
    /**
     * 事件:设备同步失败
     * */
    public static final int EVENT_DEVICES_SYNC_FAILED = 6;
    /**
     * 事件:发起断开
     * */
    public static final int EVENT_START_DISCONNECT = 7;
    /**
     * 事件:获取设备UID/PID
     * */
    public static final int EVENT_GET_DEVICE_IDENTITY_SUCCEED = 8;
    /**
     * 事件:耳机插拔
     * */
    public static final int EVENT_HEADSET_STATE_CHANGED = 9;
    /**
     * 事件:是否正在录音
     * */
    public static final int EVENT_IS_RECORDING = 10;

    /***-------------------------STATE:RECORD THE HW DEVICE CURRENT STATE----------------------------***/
    /**
     * 状态:FSM初始化
     * */
    public State mFsmInitState = new FsmInitState();
    /**
     * 状态:已断开
     * */
    public State mDisconnectedState = new DisconnectedState();
    /**
     * 状态:已连接
     * */
    public State mConnectedState = new ConnectedState();
    /**
     * 状态:设备已同步
     * */
    public State mDeviceSynchronizedState = new DeviceSynchronizedState();

    /***-------------------------ACTION:ACTION WILL PRODUCE EVENT----------------------------***/
    /**
     * 行为:FsmInitState中的enter行为
     * */
    public int FsmInitAction(){ return 0; }
    /**
     * 行为:FsmInitState中的exit行为
     * */
    public int FsmInitExitAction(){ return 0; }

    /**
     * 行为:DisconnectedState中的enter行为
     * */
    public int DisconnectedAction(){ return 0; }
    /**
     * 行为:DisconnectedState中的exit行为
     * */
    public int DisconnectedExitAction(){ return 0; }

    /**
     * 行为:ConnectedState中的enter行为
     * */
    public int ConnectedAction(){ return 0; }
    /**
     * 行为:ConnectedState中的exit行为
     * */
    public int ConnectedExitAction(){ return 0; }

    /**
     * 行为:DeviceSynchronizedState中的enter行为
     * */
    public int DeviceSynchronizedAction(){ return 0; }
    /**
     * 行为:DeviceSynchronizedState中的exit行为
     * */
    public int DeviceSynchronizedExitAction(){ return 0; }


    /***-----------------------------EVENT_ACTION-----------------------------------***/
    /**
     * 事件行为:EVENT_START_DISCONNECT
     * */
    public int EventStartDisconnectAction(){ return 0; }
    /**
     * 事件行为:EVENT_START_CONNECT
     * */
    public int EventStartConnectAction(){ return 0; }
    /**
     * 事件行为:EVENT_START_DEVICE_SYNC
     * */
    public int EventStartDeviceSyncAction(){ return 0; }
    /**
     * 事件行为:EVENT_START_DEVICE_SYNC
     * */
    public int EventGetDeviceIdentity(){ return 0; }
    /**
     * 事件行为:EVENT_HEADSET_STATE_CHANGED
     * */
    public int EventHeadsetStateChangedAction(){ return 0; }
    /**
     * 事件行为:EVENT_HEADSET_STATE_CHANGED
     * */
    public int EventIsRecordingAction(){ return 0; }

    public Fsm(Context context, String name) {
        super(context, name);

        this.TAG = name;
        this.CurrentFsmName = name;
        if (mDbg) Log.d(TAG,"Fsm");
        addState(mFsmInitState, null);
        addState(mDisconnectedState, mFsmInitState);
        addState(mConnectedState, mFsmInitState);

        addState(mConnectedState, mDisconnectedState);
        addState(mDisconnectedState, mConnectedState);

        addState(mDeviceSynchronizedState, mConnectedState);

        addState(mDisconnectedState, mDeviceSynchronizedState);

        //设置初始状态
        setInitialState(mFsmInitState);
        executorService = Executors.newFixedThreadPool(8);
    }

    @Override
    protected void onHalting() {
        synchronized (this) {
            this.notifyAll();
        }
    }

    private class FsmInitState extends State {
        @Override
        public void enter() {
            if (mDbg) Log.d(TAG,"enter FsmInitState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    FsmInitAction();
                }
            });
            super.enter();
        }

        @Override
        public void exit() {
            if (mDbg) Log.d(TAG,"exit FsmInitState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    FsmInitExitAction();
                }
            });
            super.exit();
        }

        @Override
        public boolean processMessage(Message msg) {
            if (mDbg) Log.d(TAG,"FsmInitState msg.what = " + msg.what);
            switch (msg.what){
                case EVENT_DISCONNECTED:
                    if (mDbg) Log.d(TAG,"FsmInitState:EVENT_DISCONNECTED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            transitionTo(mDisconnectedState);
                        }
                    });
                    break;
                case EVENT_CONNECTED:
                    if (mDbg) Log.d(TAG,"FsmInitState:EVENT_CONNECTED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            transitionTo(mConnectedState);
                        }
                    });
                    break;
                default:
                    break;
            }
            return super.processMessage(msg);
        }
    }

    private class DisconnectedState extends State {
        @Override
        public void enter() {
            if (mDbg) Log.d(TAG,"enter DisconnectedState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    DisconnectedAction();
                }
            });
            super.enter();
        }

        @Override
        public void exit() {
            if (mDbg) Log.d(TAG,"exit DisconnectedState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    DisconnectedExitAction();
                }
            });
            super.exit();
        }

        @Override
        public boolean processMessage(Message msg) {
            if (mDbg) Log.d(TAG,"DisconnectedState msg.what = " + msg.what);
            switch (msg.what){
                case EVENT_START_CONNECT:
                    if (mDbg) Log.d(TAG,"DisconnectedState:EVENT_START_CONNECT");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() { EventStartConnectAction(); }
                    });
                    break;
                case EVENT_DISCONNECTED:
                    if (mDbg) Log.d(TAG,"DisconnectedState:EVENT_DISCONNECTED");
                    break;
                case EVENT_CONNECTED:
                    if (mDbg) Log.d(TAG,"DisconnectedState:EVENT_CONNECTED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            transitionTo(mConnectedState);
                        }
                    });
                    break;
                case EVENT_HEADSET_STATE_CHANGED:
                    if (mDbg) Log.d(TAG,"DisconnectedState:EVENT_HEADSET_STATE_CHANGED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventHeadsetStateChangedAction();
                        }
                    });
                    break;
                case EVENT_IS_RECORDING:
                    if (mDbg) Log.d(TAG,"DisconnectedState:EVENT_IS_RECORDING");
                    isRecording = msg.arg1;
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventIsRecordingAction();
                        }
                    });
                    break;
                default:
                    break;
            }
            return super.processMessage(msg);
        }
    }

    private class ConnectedState extends State {
        @Override
        public void enter() {
            if (mDbg) Log.d(TAG,"enter ConnectedState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    ConnectedAction();
                }
            });
            super.enter();
        }

        @Override
        public void exit() {
            if (mDbg) Log.d(TAG,"exit ConnectedState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    ConnectedExitAction();
                }
            });
            super.exit();
        }

        @Override
        public boolean processMessage(Message msg) {
            if (mDbg) Log.d(TAG,"ConnectedState msg.what = " + msg.what + ", msg.arg1 = " + msg.arg1);
            switch (msg.what){
                case EVENT_START_DISCONNECT:
                    if (mDbg) Log.d(TAG,"ConnectedState:EVENT_START_DISCONNECT");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventStartDisconnectAction();
                        }
                    });
                    break;
                case EVENT_DISCONNECTED:
                    if (mDbg) Log.d(TAG,"ConnectedState:EVENT_DISCONNECTED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            transitionTo(mDisconnectedState);
                        }
                    });
                    break;
                case EVENT_START_DEVICE_SYNC:
                    if (mDbg) Log.d(TAG,"ConnectedState:EVENT_START_DEVICE_SYNC");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventStartDeviceSyncAction();
                        }
                    });
                    break;
                case EVENT_DEVICES_SYNC_SUCCEED:
                    if (mDbg) Log.d(TAG,"ConnectedState:EVENT_DEVICES_SYNC_SUCCEED");
                    DeviceType = msg.arg1;
                    Log.d(TAG,"msg.arg1 = " + msg.arg1);
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            transitionTo(mDeviceSynchronizedState);
                        }
                    });
                    break;
                case EVENT_DEVICES_SYNC_FAILED:
                    if (mDbg) Log.d(TAG,"ConnectedState:EVENT_DEVICES_SYNC_FAILED");
                    break;
                case EVENT_HEADSET_STATE_CHANGED:
                    if (mDbg) Log.d(TAG,"ConnectedState:EVENT_HEADSET_STATE_CHANGED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventHeadsetStateChangedAction();
                        }
                    });
                    break;
                case EVENT_IS_RECORDING:
                    if (mDbg) Log.d(TAG,"ConnectedState:EVENT_IS_RECORDING");
                    isRecording = msg.arg1;
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventIsRecordingAction();
                        }
                    });
                    break;
                default:
                    break;
            }
            return super.processMessage(msg);
        }
    }

    private class DeviceSynchronizedState extends State {
        @Override
        public void enter() {
            if (mDbg) Log.d(TAG,"enter DeviceSynchronizedState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    DeviceSynchronizedAction();
                }
            });
            super.enter();
        }

        @Override
        public void exit() {
            if (mDbg) Log.d(TAG,"exit DeviceSynchronizedState");
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    DeviceSynchronizedExitAction();
                }
            });
            super.exit();
        }

        @Override
        public boolean processMessage(Message msg) {
            if (mDbg) Log.d(TAG,"DeviceSynchronizedState msg.what = " + msg.what);
            switch (msg.what){
                case EVENT_START_DISCONNECT:
                    if (mDbg) Log.d(TAG,"DeviceSynchronizedState:EVENT_START_DISCONNECT");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventStartDisconnectAction();
                        }
                    });
                    break;
                case EVENT_DISCONNECTED:
                    if (mDbg) Log.d(TAG,"DeviceSynchronizedState:EVENT_DISCONNECTED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            transitionTo(mDisconnectedState);
                        }
                    });
                    break;
                case EVENT_GET_DEVICE_IDENTITY_SUCCEED:
                    if (mDbg) Log.d(TAG,"DeviceSynchronizedState:EVENT_GET_DEVICE_IDENTITY_SUCCEED");
                    DeviceUid = msg.obj.toString();
                    Log.d(TAG,"EVENT_GET_DEVICE_IDENTITY_SUCCEED, DeviceUid = " + DeviceUid);
                    break;
                case EVENT_HEADSET_STATE_CHANGED:
                    if (mDbg) Log.d(TAG,"DeviceSynchronizedState:EVENT_HEADSET_STATE_CHANGED");
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventHeadsetStateChangedAction();
                        }
                    });
                    break;
                case EVENT_IS_RECORDING:
                    if (mDbg) Log.d(TAG,"DeviceSynchronizedState:EVENT_IS_RECORDING");
                    isRecording = msg.arg1;
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            EventIsRecordingAction();
                        }
                    });
                    break;
                default:
                    break;
            }
            return super.processMessage(msg);
        }
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值