状态模式中的行为是由状态来决定的,不同的状态下有不同的行为。状态模式和策略模式的结构几乎完全一样,但它们的目的、本质却完全不一样。状态模式的行为是平行的、不可替换的,策略模式的行为是彼此独立、可相互替换的。用一句话来表述,状态模式把对象的行为包装在不同的状态对象里,每一个状态对象都有一个共同的抽象状态基类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
Android 的 Wifi 状态切换会使用 WifiController 类。
/** * WifiController is the class used to manage on/off state of WifiStateMachine for various operating * modes (normal, airplane, wifi hotspot, etc.). */ public class WifiController extends StateMachine {WifiController 类继承了 StateMachine 类。StateMachine 是一个状态机,它的实现是一种状态模式。
StateMachine 的 sendMessage 方法如下:
public void sendMessage(int what) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.sendMessage(obtainMessage(what)); }sendMessage 方法通过 SmHandler 发送消息。
SmHandler 的代码如下:
private static class SmHandler extends Handler { ... private class StateInfo { /** The state */ State state; /** The parent of this state, null if there is no parent */ StateInfo parentStateInfo; /** True when the state has been entered and on the stack */ boolean active; ... } ...StateInfo 是 SmHandler 的内部类,用来保存状态信息。state 是当前状态,parentStateInfo 是上一个状态,active 表示状态是否激活。
SmHandler 的 handleMessage 代码如下:
@Override public final void handleMessage(Message msg) { if (!mHasQuit) { ... msgProcessedState = processMsg(msg); ... performTransitions(msgProcessedState, msg); ... } }handleMessage 首先通过 processMsg 处理消息,然后通过 performTransitions 执行状态转换。
processMsg 方法如下:
private final State processMsg(Message msg) { StateInfo curStateInfo = mStateStack[mStateStackTopIndex]; if (mDbg) { mSm.log("processMsg: " + curStateInfo.state.getName()); } if (isQuit(msg)) { transitionTo(mQuittingState); } else { while (!curStateInfo.state.processMessage(msg)) { /** * Not processed */ curStateInfo = curStateInfo.parentStateInfo; if (curStateInfo == null) { /** * No parents left so it's not handled */ mSm.unhandledMessage(msg); break; } if (mDbg) { mSm.log("processMsg: " + curStateInfo.state.getName()); } } } return (curStateInfo != null) ? curStateInfo.state : null; }如果当前状态处理了消息,就返回当前状态,否则循环寻找它的上一个状态来处理。如果没有状态处理,会调用 unhandledMessage 方法。
performTransitions 方法如下:
private void performTransitions(State msgProcessedState, Message msg) { ... State orgState = mStateStack[mStateStackTopIndex].state; ... State destState = mDestState; if (destState != null) { ... while (true) { ... StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState); // flag is cleared in invokeEnterMethods before entering the target state mTransitionInProgress = true; invokeExitMethods(commonStateInfo); int stateStackEnteringIndex = moveTempStateStackToStateStack(); invokeEnterMethods(stateStackEnteringIndex); ... }orgState 是原始状态,destState 是目标状态。invokeExitMethods 先退出状态,然后用 invokeEnterMethods 进入新的状态。
WifiController 在构造是初始化了一些状态。
WifiController(Context context, WifiStateMachine wsm, Looper wifiStateMachineLooper, WifiSettingsStore wss, Looper wifiServiceLooper, FrameworkFacade f, WifiStateMachinePrime wsmp) { super(TAG, wifiServiceLooper); ... // CHECKSTYLE:OFF IndentationCheck addState(mDefaultState); addState(mStaDisabledState, mDefaultState); addState(mStaEnabledState, mDefaultState); addState(mDeviceActiveState, mStaEnabledState); addState(mStaDisabledWithScanState, mDefaultState); addState(mEcmState, mDefaultState); // CHECKSTYLE:ON IndentationCheck ... }WifiController 使用 addState 添加状态。
这里的 6 个 addState 方法没有按照正常的空格缩进。为了表示层级关系,越底层的状态缩进的越多。
mDefaultState 是最顶层的 State,mStaDisabledState、mStaEnabledState、mStaDisabledWithScanState、mEcmState 是第二层的 State,mDeviceActiveState 是最底层的 State。
addState 方法如下:
private final StateInfo addState(State state, State parent) { ... StateInfo parentStateInfo = null; if (parent != null) { parentStateInfo = mStateInfo.get(parent); if (parentStateInfo == null) { // Recursively add our parent as it's not been added yet. parentStateInfo = addState(parent, null); } } ... stateInfo.state = state; stateInfo.parentStateInfo = parentStateInfo; stateInfo.active = false; ... return stateInfo; }addState 方法通过递归的方式构造了 stateInfo。
状态之间不是跨越式转换的,当前状态只能转换到上一个状态或者下一个状态。
