State设计模式
将对象的状态封装成1个对象,在不同状态下,同样的调用将执行不同的操作

State设计模式类图
Context可维护多个State子类的实例,每个实例代表1种状态。State定义1个接口,以封装与Context的1个特定状态相关的行为,即Context只需固定调用State→Handle方法,即可将与状态相关的请求委托给当前ConcreteState对象的Handle方法处理。
状态机的四大概念
State
1个状态机至少要包含2个状态。
Event
事件就是执行某个操作的触发条件或口令。
Action
事件发生以后要执行动作。
Transition
从1个状态变化为另1个状态。
状态机使用步骤
1. 定义1个类,继承StateMachine
public class GwsdModeController extends StateMachine {
2. 定义各个状态,并且重写enter(),exit(),processMessage()
enter()是每次进入都会执行类似构造函数
exit()类似析构函数
processMessage()用来处理不同的请求
private class InacviceState extends State {
@Override
public void enter() {
mState = "InacviceState";
logd("enter");
}
@Override
public void exit() {
logd("exit");
}
@Override
public boolean processMessage(Message msg) {
boolean retVal = HANDLED;
logd("msg=" + msgToString(msg));
AsyncResult ar = null;
Message callback = null;
if (msg.obj instanceof AsyncResult) {
ar = (AsyncResult) msg.obj;
callback = (Message) ar.userObj;
} else if (msg.obj instanceof Message) {
callback = (Message) msg.obj;
}
switch(msg.what) {
case EVENT_SET_NORMAL_MODE:
if (msg.arg1 == 0) {
AsyncResult.forMessage(callback, null, null);
callback.sendToTarget();
return retVal;
}
MtkRIL mtkRil = getRilService(msg, false);
if (mtkRil != null) {
msg = obtainMessage(EVENT_SET_NORMAL_MODE_COMPLETED,
msg.arg1, -1, msg.obj);
mtkRil.setGwsdMode(msg.arg1, KEEP_BY_IP, KEEP_START, msg);
transitionTo(mActivatingState);
}
break;
default:
logd("no action");
retVal = NOT_HANDLED;
break;
}
return retVal;
}
}
3. 调用addState构建状态树
状态机从添加状态开始,调用 addState 方法。每个State都可添加1个自身的State和1个parentState。若在当前的State中没能处理发送来的msg时,就要向上找其父State来处理,依次向上遍历,若所有的State都不能处理就会调用SmHandler:unhandledMessage来处理。
public GwsdModeController(String name, int phoneId,
Handler handler, Context context) {
super(name, handler);
。。。。。。
addState(mDefaultState);
addState(mInacviceState, mDefaultState);
addState(mActivatingState, mDefaultState);
addState(mActiveState, mDefaultState);
addState(mDeactivatingState, mDefaultState);
。。。。。。
}
几种状态的依赖关系如下:

4. setInitialState()设置初始状态
public GwsdModeController(String name, int phoneId,
Handler handler, Context context) {
super(name, handler);
。。。。。。
//mInacviceState为初始状态
setInitialState(mInacviceState);
。。。。。。
}
5. 调用start(),状态机开始工作
public GwsdModeController(String name, int phoneId,
Handler handler, Context context) {
。。。。。。
start();
}
6. 使用sendMessage()向状态机中发送消息
sendMessage发送消息时,StateMachine就会找到当前的State调用其processMessage来做相应的处理动作
public void setUserSelectionMode(boolean action, Message onComplete) {
logd("setUserSelectionMode: action = " + action);
synchronized(mLock) {
int mode = action ? 1 : 0;
Message msg = obtainMessage(EVENT_SET_NORMAL_MODE, mode, -1);
msg.obj = onComplete;
sendMessage(msg);
}
}
7. transitionTo()从当前转移到另外1个状态
transitionTo(mActivatingState);
StateMachine核心类


SmHandler
在 StateMachine中,开启了1个线程HandlerThread,对应的Handler为SmHandler。因此上文案例中对应状态的 processMessage(Message msg),均在HandlerThread线程中执行。
是消息处理派发和状态控制切换的核心,运行在单独的线程上
StateMachine类对外提供状态相关操作的接口方法,而SmHandler类则是作为StateMachine状态机的核心,负责Handler消息的发送和接收,用来管理和更新State对象。

StateMachine的构造方法
StateMachine的构造方法中,创建并启动了1个线程HandlerThread;
protected StateMachine(String name) {
// 创建 HandlerThread
mSmThread = new HandlerThread(name);
mSmThread.start();
// 获取HandlerThread对应的Looper
Looper looper = mSmThread.getLooper();
// 初始化 StateMachine
initStateMachine(name, looper);
}
initStateMachine方法中,创建了HandlerThread线程对应的Handler SmHandler
private void initStateMachine(String name, Looper looper) {
mName = name;
mSmHandler = new SmHandler(looper, this);
}
SmHandler构造方法中,向状态机中添加了2个状态:1个状态为状态机的暂停状态mHaltingState、1个状态为状态机的退出状态mQuittingState
private SmHandler(Looper looper, StateMachine sm) {
super(looper);
mSm = sm;
// 添加状态:暂停 和 退出
// 这2个状态 无父状态
addState(mHaltingState, null);
addState(mQuittingState, null);
}
mHaltingState状态,顾名思义让状态机暂停,其对应的processMessage(Message msg),返回值为true,将消息消费掉,但不处理消息。从而使状态机状态停顿到mHaltingState状态
mQuittingState状态,若进入该状态, 状态机将退出。HandlerThread线程对应的Looper将退出,HandlerThread线程会被销毁,所有加入到状态机的状态被清空。
StateMachine的start方法
状态机的初始化说完,下边来说状态机的启动方法start()
public void start() {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
// StateMachine 未进行初始化,为什么不抛出1个异常
if (smh == null) {
return;
}
// 完成状态机建设
smh.completeConstruction();
}
从以上代码可看到,其中只有1个方法completeConstruction(),用于完成状态机的建设。
private final void completeConstruction() {
int maxDepth = 0;
// 循环判断所有状态,看看哪1个链最长,得出深度
for (StateInfo si : mStateInfoHashMap.values()) {
int depth = 0;
for (StateInfo i = si; i != null; depth++) {
i = i.parentStateInfo;
}
if (maxDepth < depth) {
maxDepth = depth;
}
}
// 状态堆栈
mStateStack = new StateInfo[maxDepth];
// 临时状态堆栈
mTempStateStack = new StateInfo[maxDepth];
// 初始化堆栈
setupInitialStateStack();
// 发送初始化完成的消息(消息放入到队列的最前边)
sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
}
- maxDepth是状态机中,最长依赖链的长度。
- mStateStack与mTempStateStack为2个用数组实现的堆栈。这2个堆栈的最大长度,即为maxDepth。其用来存储当前活跃状态与当前活跃状态的父状态、父父状态、...等
- setupInitialStateStack();完成状态的初始化,将当前的活跃状态放入到mStateStack堆栈中。
下边来具体说setupInitialStateStack()中,如何完成栈的初始化。
private final void setupInitialStateStack() {
// 获取初始状态信息
StateInfo curStateInfo = mStateInfoHashMap.get(mInitialState);
//
for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
// 初始状态 放入临时堆栈
mTempStateStack[mTempStateStackCount] = curStateInfo;
// 当前状态的 所有父状态 1级级放入堆栈
curStateInfo = curStateInfo.parentStateInfo;
}
// 清空 状态堆栈
// Empty the StateStack
mStateStackTopIndex = -1;
// 临时堆栈 换到 状态堆栈
moveTempStateStackToStateStack();
}
- 将初始化状态放入 mTempStateStack堆栈中
- 将初始化状态的父状态、父父状态、父父父状态... 都11放入到mTempStateStack堆栈中

然后moveTempStateStackToStateStack()中,mTempStateStack出栈,mStateStack入栈,将所有状态信息导入到mStateStack堆栈,并清空mTempStateStack堆栈。

到这里,初始化基本完成,但还落下1部分代码没说:
// 发送初始化完成的消息(消息放入到队列的最前边)
sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
- 发送1个初始化完成的消息到SmHandler当中。
下边来看下SmHandler的handleMessage(Message msg)方法:
public final void handleMessage(Message msg) {
// 处理消息
if (!mHasQuit) {
// 保存传入的消息
mMsg = msg;
State msgProcessedState = null;
// 已完成初始化
if (mIsConstructionCompleted) {
// ..
}
// 接收到 初始化完成的消息
else if (!mIsConstructionCompleted
&& (mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {
/** Initial one time path. */
// 初始化完成
mIsConstructionCompleted = true;
// 调用堆栈中状态的enter方法,并将堆栈中的状态设置为活跃状态
invokeEnterMethods(0);
} else {
// ..
}
// 执行Transition
performTransitions(msgProcessedState, msg);
}
}
- 接收到初始化完成的消息后mIsConstructionCompleted = true;对应的标志位变过来
- 执行 invokeEnterMethods方法将mStateStack堆栈中的所有状态设置为活跃状态,并由父—>子的顺序,执行堆栈中状态的enter()
- performTransitions(msgProcessedState, msg);在start()时,其中的内容全部不执行,因此先不介绍。
invokeEnterMethods方法的方法体如下:
private final void invokeEnterMethods(int stateStackEnteringIndex) {
for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
if (stateStackEnteringIndex == mStateStackTopIndex) {
// Last enter state for transition
mTransitionInProgress = false;
}
if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
mStateStack[i].state.enter();
mStateStack[i].active = true;
}
mTransitionInProgress = false; // ensure flag set to false if no methods called
}
- 可看到,其将mStateStack堆栈中的所有状态设置为活跃状态,并由父—>子的顺序,执行堆栈中状态的enter()
到此start()完成,最终mStateStack堆栈状态,也如上图所示。
状态转化
- 通过调用sendMessage方法,向SmHandler中发送1个消息,来触发状态转化。
- 可说 sendMessage为状态转化的导火索。
下边,再次看下SmHandler的handleMessage(Message msg):
public final void handleMessage(Message msg) {
// 处理消息
if (!mHasQuit) {
// 保存传入的消息
mMsg = msg;
State msgProcessedState = null;
// 已完成初始化
if (mIsConstructionCompleted) {
// 处理消息的状态
msgProcessedState = processMsg(msg);
}
// 收到 初始化完成的消息
else if (!mIsConstructionCompleted
&& (mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {
// 初始化完成
mIsConstructionCompleted = true;
// 调用堆栈中状态的enter方法,并将堆栈中的状态设置为活跃状态
invokeEnterMethods(0);
} else {
throw new RuntimeException("StateMachine.handleMessage: "
+ "The start method not called, received msg: " + msg);
}
// 执行Transition
performTransitions(msgProcessedState, msg);
}
}
- 因为初始化已经完成,代码会直接走到processMsg(msg);中。
来看processMsg(msg);:
private final State processMsg(Message msg) {
// 堆栈中找到当前状态
StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
// 是否为退出消息
if (isQuit(msg)) {
// 转化为退出状态
transitionTo(mQuittingState);
} else {
// 状态返回true 则是可处理此状态
// 状态返回false 则不可处理
while (!curStateInfo.state.processMessage(msg)) {
// 当前状态的父状态
curStateInfo = curStateInfo.parentStateInfo;
// 父状态未null
if (curStateInfo == null) {
// 回调到未处理消息方法中
mSm.unhandledMessage(msg);
break;
}
}
}
// 消息处理后,返回当前状态信息
// 若消息不处理,则返回其父状态处理,返回处理消息的父状态
return (curStateInfo != null) ? curStateInfo.state : null;
}
- 代码会直接走到while (!curStateInfo.state.processMessage(msg))执行mStateStack堆栈中,最上层状态的 processMessage(msg)。
- 这里若mStateStack堆栈中状态的processMessage(msg)返回true,则表示其消费掉了此消息;若其返回false,则表示不消费此消息,那么该消息将继续向其父状态进行传递;
- 最终将返回,消费掉该消息的状态。
这里,堆栈对上层的状态为InacviceState。所以看下其对应的processMessage(msg)。
private class 在SleepState状态的processMessage(Message msg)方法中,其收到MSG_WAKEUP消息后,会调用transitionTo(mWorkState);方法,将目标状态设置为mWorkState。 extends State {
@Override
public void enter() {
mState = "InacviceState";
logd("enter");
}
@Override
public void exit() {
logd("exit");
}
@Override
public boolean processMessage(Message msg) {
boolean retVal = HANDLED;
logd("msg=" + msgToString(msg));
AsyncResult ar = null;
Message callback = null;
if (msg.obj instanceof AsyncResult) {
ar = (AsyncResult) msg.obj;
callback = (Message) ar.userObj;
} else if (msg.obj instanceof Message) {
callback = (Message) msg.obj;
}
switch(msg.what) {
case EVENT_SET_NORMAL_MODE:
if (msg.arg1 == 0) {
AsyncResult.forMessage(callback, null, null);
callback.sendToTarget();
return retVal;
}
MtkRIL mtkRil = getRilService(msg, false);
if (mtkRil != null) {
msg = obtainMessage(EVENT_SET_NORMAL_MODE_COMPLETED,
msg.arg1, -1, msg.obj);
mtkRil.setGwsdMode(msg.arg1, KEEP_BY_IP, KEEP_START, msg);
transitionTo(mActivatingState);
}
break;
default:
logd("no action");
retVal = NOT_HANDLED;
break;
}
return retVal;
}
}
- 在SleepState状态的processMessage(Message msg)中,其收到EVENT_SET_NORMAL_MODE消息后,会调用transitionTo(mActivatingState);,将目标状态设置为mActivatingState。
看下transitionTo(mWorkState);:
private final void transitionTo(IState destState) {
mDestState = (State) destState;
}
- 可看到,transitionTo(IState destState),只是1个简单的状态赋值。
下边回到SmHandler的handleMessage(Message msg):
-
会执行到SmHandler.handleMessage(Message msg)的performTransitions(msgProcessedState, msg)之中。
-
而这里传入的参数msgProcessedState为mActivatingState。
private void performTransitions(State msgProcessedState, Message msg) { // 当前状态 State orgState = mStateStack[mStateStackTopIndex].state; // ... // 目标状态 State destState = mDestState; if (destState != null) { while (true) { // 目标状态 放入temp 堆栈 // 目标状态的 父状态 作为参数 传入下1级 StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState); // commonStateInfo 状态的子状态全部退栈 invokeExitMethods(commonStateInfo); // 目标状态入栈 int stateStackEnteringIndex = moveTempStateStackToStateStack(); // 入栈状态 活跃 invokeEnterMethods(stateStackEnteringIndex); //... moveDeferredMessageAtFrontOfQueue();
if (destState != mDestState) { // A new mDestState so continue looping destState = mDestState; } else { // No change in mDestState so we're done break; } } mDestState = null; } // ...}
-
以上方法中 传入的参数msgProcessedState为InacviceState
-
方法中destState目标状态为 mActivatingState
此时performTransitions(State msgProcessedState, Message msg)中内容的执行示意图:

A、目标状态放入到mTempStateStack队列中
// 目标状态 放入temp 堆栈
// 目标状态的 父状态 作为参数 传入下1级
StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
- 1、将mActivatingState状态放入到mTempStateStack堆栈中
- 2、将mActivatingState状态的非活跃父状态mDefaultState11入mTempStateStack堆栈
B、commonStateInfo状态在mStateStack堆栈中的子状态退堆栈
commonStateInfo为setupTempStateStackWithStatesToEnter(destState);方法的返回参数。这里是mDefaultState
// commonStateInfo 状态的子状态全部退栈
invokeExitMethods(commonStateInfo);
- 1、mDefaultState作为参数传入到invokeExitMethods(commonStateInfo);方法中
- 2、其方法内容为,将mDefaultState状态的全部子状态退堆栈
以上代码的执行示意图:

C、mTempStateStack全部状态出堆栈,mStateStack入堆栈
// 目标状态入栈
int stateStackEnteringIndex = moveTempStateStackToStateStack();
// 入栈状态 活跃
invokeEnterMethods(stateStackEnteringIndex);
- moveTempStateStackToStateStack中:mTempStateStack全部状态出堆栈,mStateStack入堆栈
- invokeEnterMethods(stateStackEnteringIndex);中,将新加入的状态设置为活跃状态;并调用其对应的enter()。
最终的堆栈状态为:

参考: