1. StateMachineJar的封装
把源码的如下3个文件,提取为jar包使用就可以
frameworks/base/core/java/com/android/internal/util/StateMachine.java
frameworks/base/core/java/com/android/internal/util/State.java
frameworks/base/core/java/com/android/internal/util/IState.java
2. 使用示例
StateMachine的基本使用必须按如下四个步骤进行,缺一不可:
- 继承StateMachine,StateMachine类的构造函数是Protect访问权限,所以只能通过继承实现实例化
- 通过addState方法构造状态层次结构(树形结构,可多棵),状态层次结构根据状态转移图构建,各种状态需要继承State类,实现自己相应业务逻辑
- 通过setInitialState设置初始状态
- 调用start方法启动状态机
其他常用API如下表所示:
Method | Description |
---|---|
quit() | 停止状态机,会进入QuttingState |
sendMessage(Message msg) | 发送一个消息,供各状态处理 |
deferMessage(Message msg) | 发送一个延迟消息,在下一次状态转换时,才会被放入消息队列 |
transitionTo(IState state) | 转移至相应状态 |
transitionToHaltingState() | 进入HaltingState |
示例:
继承StateMachine并初始化
package com.mtest.statemachine;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.bluesky.statemachinejar.State;
import com.bluesky.statemachinejar.StateMachine;
import com.mtest.statemachine.state.ErrorState;
import com.mtest.statemachine.state.ExitState;
import com.mtest.statemachine.state.IdleState;
import com.mtest.statemachine.state.NormalState;
import com.mtest.statemachine.state.StartRecgState;
import java.util.HashMap;
import java.util.Map;
public class FaceStateMachine extends StateMachine {
private static final String NAME = "FaceStateMachine";
private static final String TAG = "FaceStateMachine";
/*定义的几个状态机状态,包括初始状态,开始识别,识别正常,识别异常,退出识别*/
public static final int IDLE_STATE = 1;
public static final int START_RECG_STATE = 2;
public static final int RECG_NORMAL_STATE = 3;
public static final int RECG_ERROR_STATE = 4;
public static final int RECG_EXIT_STATE = 5;
private static volatile FaceStateMachine sFaceStateMachine;
private Map<String, State> mStateMap = new HashMap<>();
/*继承的StateMachine,super需要添加状态机名字,并且运行在主线程*/
protected FaceStateMachine() {
super(NAME, Looper.getMainLooper());
initStateMachine();
}
/*状态机这里采用单例模式,用于管理*/
public static FaceStateMachine get() {
synchronized (FaceStateMachine.class) {
if (sFaceStateMachine == null) {
synchronized (FaceStateMachine.class) {
sFaceStateMachine = new FaceStateMachine();
}
}
}
return sFaceStateMachine;
}
/*
* 构造状态机需要添加初始状态,StateMachine是树结构的状态机,因此要添加父节点
* setInitialState:设置初始状态 start开始状态机
* */
private void initStateMachine() {
IdleState idleState = new IdleState();
StartRecgState startRecg = new StartRecgState();
addInitStateMachine(idleState);
addInitStateMachine(startRecg);
addInitStateMachine(new NormalState(), startRecg);
addInitStateMachine(new ExitState(), startRecg);
addInitStateMachine(new ErrorState(), startRecg);
setInitialState(idleState);
start();
}
/*
* 调用addState完成添加状态机,可以直接添加,也可以添加父类关系
*
* mStateMap用于保存,状态State的集合,通过getState()获取状态名,用于切状态
* */
private void addInitStateMachine(State childState) {
mStateMap.put(childState.getClass().getSimpleName(),childState);
addState(childState);
}
private void addInitStateMachine(State childState, State parentState) {
mStateMap.put(childState.getClass().getSimpleName(),childState);
addState(childState, parentState);
}
public State getState(String name) {
return mStateMap.get(name);
}
/*
* 如果不添加sendMessage,直接调用transitionTo,根本就不会执行切状态
*
* */
/*模拟发送消息*/
public void doSendEventByStartRecg() {
Log.d(TAG , "doSendEventByStartRecg:");
transitionTo(getState(StartRecgState.class.getSimpleName()));
sendMessage(START_RECG_STATE);
}
}
base状态机
package com.mtest.statemachine.state;
import android.os.Message;
import android.util.Log;
import com.bluesky.statemachinejar.State;
import com.bluesky.statemachinejar.StateMachine;
import com.mtest.statemachine.FaceStateMachine;
/*用于自己创建的状态机基类,作为所有state继承用*/
public class BaseState extends State {
public static final String TAG = BaseState.class.getSimpleName();
/*
* 状态机进程时候执行,像初始化
* */
@Override
public void enter() {
super.enter();
Log.d(TAG,"enter...");
}
/*退出时候执行,释放资源*/
@Override
public void exit() {
super.exit();
Log.d(TAG,"exit...");
}
/*
*消息处理,发送消息后才能切换状态机,不知道为什么
* */
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case FaceStateMachine.START_RECG_STATE:
Log.d(TAG, "processMessage: START_RECG_STATE");
break;
case FaceStateMachine.RECG_NORMAL_STATE:
Log.d(TAG, "processMessage: RECG_NORMAL_STATE");
break;
case FaceStateMachine.RECG_ERROR_STATE:
Log.d(TAG, "processMessage: RECG_ERROR_STATE");
break;
case FaceStateMachine.RECG_EXIT_STATE:
Log.d(TAG, "processMessage: RECG_EXIT_STATE");
break;
default:
break;
}
return StateMachine.NOT_HANDLED;
}
@Override
public String getName() {
return super.getName();
}
}
定义一个状态
package com.mtest.statemachine.state;
import android.os.Message;
import android.util.Log;
import com.mtest.presenter.StateMessageHander;
import com.mtest.statemachine.FaceStateMachine;
public class ExitState extends BaseState{
public static final String TAG = ExitState.class.getSimpleName();
@Override
public void enter() {
super.enter();
Log.d(TAG, "ExitState: enter");
StateMessageHander.getInstance().sendEmptyMessage(StateMessageHander.DO_RECG_EXIT_STATE);
}
@Override
public void exit() {
super.exit();
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case FaceStateMachine.START_RECG_STATE:
Log.d(TAG, "processMessage: START_RECG_STATE");
//FaceStateMachine.get().transitionTo(FaceStateMachine.get().getState());
break;
case FaceStateMachine.RECG_NORMAL_STATE:
Log.d(TAG, "processMessage: RECG_NORMAL_STATE");
break;
case FaceStateMachine.RECG_ERROR_STATE:
Log.d(TAG, "processMessage: RECG_ERROR_STATE");
break;
case FaceStateMachine.RECG_EXIT_STATE:
Log.d(TAG, "processMessage: RECG_EXIT_STATE");
break;
default:
break;
}
return super.processMessage(msg);
}
}
3. 使用注意
通常,我们会在 State.processMessage 内部,通过调用 transitionTo 函数执行一次状态转换,而调用这个函数只是将你要转换的状态存入一个临时的对象中:
protected final void transitionTo(IState destState) {
mSmHandler.transitionTo(destState);
}
private final void transitionTo(IState destState) {
mDestState = (State) destState;
}
复制代码真正的状态转换将发生在 SmHandler.handleMessage 函数执行之后:
public final void handleMessage(Message msg) {
if (!mHasQuit) {
...
performTransitions(msgProcessedState, msg);//变更状态
}
}
参考链接