提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
使用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);
}
}
}