概念
有限狀態(tài)機(jī)即FSM,簡稱狀態(tài)機(jī),表示有限個狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動作等行為的數(shù)學(xué)模型。
狀態(tài)機(jī)可以描述為一個有向圖樹,有一組節(jié)點(diǎn)和一組轉(zhuǎn)移函數(shù)組成。狀態(tài)機(jī)通過相應(yīng)一些列事件運(yùn)行。每個
事件都屬于當(dāng)前結(jié)點(diǎn)的轉(zhuǎn)移函數(shù)的控制范圍內(nèi),其中函數(shù)的范圍是一個節(jié)點(diǎn)的子集。函數(shù)返回下一個節(jié)點(diǎn)。這些節(jié)點(diǎn)至少有一個終態(tài),到達(dá)終態(tài),狀態(tài)機(jī)停止。
Android StateMachine
Android 系統(tǒng)使用狀態(tài)機(jī)處理不同的狀態(tài),可以避免分支語句導(dǎo)致的程序閱讀性差以及擴(kuò)展問題。
使用類

- IState.java 狀態(tài)接口,每個狀態(tài)必須實(shí)現(xiàn)的接口
- void enter() 狀態(tài)進(jìn)入時調(diào)用
- void exit() 狀態(tài)退出時調(diào)用
- boolean processMessage(Message msg) 消息處理函數(shù)
- State.java 默認(rèn)實(shí)現(xiàn)的IState接口的狀態(tài), 需要實(shí)現(xiàn)新的狀態(tài)時,一般只需要集成State重寫里面方法即可
- StateInfo.java 狀態(tài)節(jié)點(diǎn)信息,類似鏈表節(jié)點(diǎn)
- StateMachine.java 定義狀態(tài)層次關(guān)系以及狀態(tài)轉(zhuǎn)換。根據(jù)實(shí)際需求繼承StateMachine,實(shí)現(xiàn)自己的狀態(tài)管理。
狀態(tài)機(jī)重點(diǎn)時SmHandler類
StateMachine
StateMachine有3個構(gòu)造函數(shù)
protected StateMachine(String name) {
mSmThread = new HandlerThread(name);
mSmThread.start();
Looper looper = mSmThread.getLooper();
initStateMachine(name, looper);
}
protected StateMachine(String name, Handler handler) {
initStateMachine(name, handler.getLooper());
}
protected StateMachine(String name, Looper looper) {
initStateMachine(name, looper);
}
private void initStateMachine(String name, Looper looper) {
mName = name;
mSmHandler = new SmHandler(looper, this);
}
常用的為protected StateMachine(String name)方法創(chuàng)建一個狀態(tài)機(jī)。
mSmThread為HandlerThread,作為消息循環(huán)線程
mSmHandler為handler用來處理消息
在狀態(tài)機(jī)維護(hù)一個狀態(tài)數(shù)(或者狀態(tài)層次關(guān)系),每個狀態(tài)的節(jié)點(diǎn)信息存儲在StateInfo中
StateInfo 節(jié)點(diǎn)信息
/**
* Information about a state.
* Used to maintain the hierarchy.
*/
private class StateInfo {
/** The state */
State state; //節(jié)點(diǎn)信息
/** The parent of this state, null if there is no parent */
StateInfo parentStateInfo; //父節(jié)點(diǎn)信息
/** True when the state has been entered and on the stack */
boolean active; //節(jié)點(diǎn)入棧,且已經(jīng)激活
/**
* Convert StateInfo to string
*/
@Override
public String toString() {
return "state=" + state.getName() + ",active=" + active + ",parent="
+ ((parentStateInfo == null) ? "null" : parentStateInfo.state.getName());
}
}
與鏈表區(qū)別是:鏈表中存儲的下一個子節(jié)點(diǎn)的信息,在狀態(tài)樹節(jié)點(diǎn)中存儲的不是子節(jié)點(diǎn)而是父節(jié)點(diǎn)信息;有點(diǎn)便于迅速查找父節(jié)點(diǎn),當(dāng)該節(jié)點(diǎn)無法處理此消息時,可以直接轉(zhuǎn)給父節(jié)點(diǎn)處理。
狀態(tài)機(jī)的構(gòu)建
protected final void addState(State state) {
mSmHandler.addState(state, null);
}
狀態(tài)機(jī)構(gòu)建使用addState()方法,addState調(diào)用mSmHandler.addState()方法完成整個構(gòu)建過程。后面會看到狀態(tài)機(jī)的很多工作都是mSmHandler來完成。
/**
* Add a new state to the state machine. Bottom up addition
* of states is allowed but the same state may only exist
* in one hierarchy.
*
* @param state the state to add
* @param parent the parent of state
* @return stateInfo for this state
*/
private final StateInfo addState(State state, State parent) {
if (mDbg) {
mSm.log("addStateInternal: E state=" + state.getName() + ",parent="
+ ((parent == null) ? "" : parent.getName()));
}
StateInfo parentStateInfo = null;
if (parent != null) {
parentStateInfo = mStateInfo.get(parent);
//存在父節(jié)點(diǎn),但不在狀態(tài)樹中,添加進(jìn)來
if (parentStateInfo == null) {
// Recursively add our parent as it's not been added yet.
//此處為遞歸調(diào)用
parentStateInfo = addState(parent, null);
}
}
//狀態(tài)不在狀態(tài)樹中,添加進(jìn)來
StateInfo stateInfo = mStateInfo.get(state);
if (stateInfo == null) {
//將新state包裝成StateInfo,存放在map中
stateInfo = new StateInfo();
mStateInfo.put(state, stateInfo);
}
// Validate that we aren't adding the same state in two different hierarchies.
//每個狀態(tài)只能有一個父狀態(tài)
if ((stateInfo.parentStateInfo != null)
&& (stateInfo.parentStateInfo != parentStateInfo)) {
throw new RuntimeException("state already added");
}
//認(rèn)親
stateInfo.state = state;
stateInfo.parentStateInfo = parentStateInfo;
stateInfo.active = false;
if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
return stateInfo;
}
addState()方法將每個新添加進(jìn)來的狀態(tài)封裝成StateInfo,添加進(jìn)狀態(tài)樹中,如果該狀態(tài)的父節(jié)點(diǎn)不在狀態(tài)樹中,遞歸調(diào)用addState()添加進(jìn)狀態(tài)樹中。
StateInfo存儲父節(jié)點(diǎn)信息,這樣可以通過StateInfo將每個節(jié)點(diǎn)聯(lián)系在一起。狀態(tài)機(jī)中所節(jié)點(diǎn)都存儲在HashMap<State, StateInfo>()的鍵值對中,
每個狀態(tài)只能有一個父節(jié)點(diǎn)
狀態(tài)機(jī)啟動
/**
* Start the state machine.
*/
public void start() {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
/** Send the complete construction message */
smh.completeConstruction();
}
start()調(diào)用smh.completeConstruction()完成狀體機(jī)構(gòu)建
/**
* Complete the construction of the state machine.
*/
private final void completeConstruction() {
if (mDbg) mSm.log("completeConstruction: E");
/**
* Determine the maximum depth of the state hierarchy
* so we can allocate the state stacks.
*/
//計(jì)算狀態(tài)樹最大深度,用于創(chuàng)建狀態(tài)樹容量
//狀態(tài)樹記錄某個節(jié)點(diǎn)到根節(jié)點(diǎn)的狀態(tài)路徑,長度不會超過maxDeep
int maxDepth = 0;
for (StateInfo si : mStateInfo.values()) {
int depth = 0;
for (StateInfo i = si; i != null; depth++) {
i = i.parentStateInfo;
}
if (maxDepth < depth) {
maxDepth = depth;
}
}
if (mDbg) mSm.log("completeConstruction: maxDepth=" + maxDepth);
//根據(jù)狀態(tài)棧的最大節(jié)點(diǎn)數(shù),創(chuàng)建mStateStack,mTempStateStack狀態(tài)棧
mStateStack = new StateInfo[maxDepth];
mTempStateStack = new StateInfo[maxDepth];
//將狀態(tài)路徑存入狀態(tài)棧
setupInitialStateStack();
/** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
/*
狀態(tài)棧中存儲當(dāng)前節(jié)點(diǎn)到根節(jié)點(diǎn)的所有狀態(tài),根節(jié)點(diǎn)位于mStateStack的0位置
*/
//開啟狀態(tài)數(shù);通過發(fā)送SM_INIT_CMD消息,通知狀態(tài)樹可以工作,異步調(diào)用enter方法
sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
if (mDbg) mSm.log("completeConstruction: X");
}
主要工作
- 遍歷狀態(tài)樹中的節(jié)點(diǎn),獲取樹的最大節(jié)點(diǎn)數(shù)maxDeep
- 使用棧來記錄某個節(jié)點(diǎn)到根節(jié)點(diǎn)的狀態(tài)路徑,路徑不超過maxDeep
- 根據(jù)當(dāng)前節(jié)點(diǎn)和樹的最大節(jié)點(diǎn)數(shù),調(diào)用setupInitialStateStack創(chuàng)建兩個狀態(tài)棧
- 初始化完畢,發(fā)送SM_INIT_CMD消息,表示狀態(tài)樹構(gòu)建完成
setupInitialStateStack 填充棧數(shù)據(jù)
/**
* Initialize StateStack to mInitialState.
*/
private final void setupInitialStateStack() {
if (mDbg) {
mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
}
//根據(jù)第一個初始狀態(tài)
StateInfo curStateInfo = mStateInfo.get(mInitialState);
for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
mTempStateStack[mTempStateStackCount] = curStateInfo;
curStateInfo = curStateInfo.parentStateInfo;
}
//循環(huán)完畢,根節(jié)點(diǎn)位于棧頂,初始節(jié)點(diǎn)位于棧底
// Empty the StateStack,清空mStateStack
mStateStackTopIndex = -1;
//將temporary stack棧中數(shù)據(jù)反序添沖到state stack中
//這是根節(jié)點(diǎn)位于棧底(index=0),當(dāng)前節(jié)點(diǎn)位于棧頂
moveTempStateStackToStateStack();
}
根據(jù)當(dāng)前節(jié)點(diǎn),遍歷所有父節(jié)點(diǎn),將當(dāng)前節(jié)點(diǎn)到根節(jié)點(diǎn)的信息存儲在mTempStateStack中,循環(huán)過后當(dāng)前節(jié)點(diǎn)位于棧底(index=0),根節(jié)點(diǎn)位于棧頂
調(diào)用moveTempStateStackToStateStack將mTempStateStack中樹反轉(zhuǎn)存儲到mStateStack中。
moveTempStateStackToStateStack 反轉(zhuǎn)數(shù)據(jù)
/**
* Move the contents of the temporary stack to the state stack
* reversing the order of the items on the temporary stack as
* they are moved.
*
* 將temporary stack棧中數(shù)據(jù)反序添加到state stack中
*
* 在mStateStack已有節(jié)點(diǎn)的基礎(chǔ)上添加新節(jié)點(diǎn),添加完成當(dāng)前節(jié)點(diǎn)位于棧頂
*
* @return index into mStateStack where entering needs to start
*/
private final int moveTempStateStackToStateStack() {
//startingIndex 表示mStateStack接受新狀態(tài)的其實(shí)位置,
//不是每次都從0開始
int startingIndex = mStateStackTopIndex + 1;
//mTempStateStack個數(shù)
int i = mTempStateStackCount - 1;
int j = startingIndex;
while (i >= 0) {
if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
mStateStack[j] = mTempStateStack[i];
j += 1;
i -= 1;
}
//invokeEnterMethods 會使用到這個變量
//新狀態(tài)棧位置mStateStackTopIndex
mStateStackTopIndex = j - 1;
if (mDbg) {
mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
+ ",startingIndex=" + startingIndex + ",Top="
+ mStateStack[mStateStackTopIndex].state.getName());
}
return startingIndex;
}
當(dāng)狀態(tài)處理完畢,發(fā)送SM_INIT_CMD,Smhandler從消息隊(duì)列中取出消息,完成狀態(tài)機(jī)初始化工作
if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
&& (mMsg.obj == mSmHandlerObj)) {
/** Initial one time path. */
//根據(jù)SM_INIT_CMD消息表明構(gòu)建任務(wù)完成,設(shè)置完成標(biāo)志,開始處理消息
mIsConstructionCompleted = true;
//循環(huán)調(diào)用mStateStack中enter方法并將狀態(tài)設(shè)為激活狀態(tài)
invokeEnterMethods(0);
}
將mIsConstructionCompleted標(biāo)記變量設(shè)置為true,表示完成初始化,調(diào)用invokeEnterMethods,將每個狀態(tài)設(shè)為激活狀態(tài),并調(diào)用enter()方法
/**
* Invoke the enter method starting at the entering index to top of state stack
* 從stateStackEnteringIndex開始循環(huán)調(diào)用mStateStack中enter方法并將狀態(tài)設(shè)為激活狀態(tài)
*/
private final void invokeEnterMethods(int stateStackEnteringIndex) {
for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
mStateStack[i].state.enter();
mStateStack[i].active = true;
}
//enter 方法是進(jìn)入狀態(tài)的必要工作,enter方法執(zhí)行完,對應(yīng)狀態(tài)開始進(jìn)行消息處理 processMessage
}
狀態(tài)處理
/**
* Handle messages sent to the state machine by calling
* the current state's processMessage. It also handles
* the enter/exit calls and placing any deferred messages
* back onto the queue when transitioning to a new state.
*
* 調(diào)用當(dāng)前狀態(tài)處理消息,
*
* 調(diào)整更新狀態(tài)棧stateStack的內(nèi)容
*/
@Override
public final void handleMessage(Message msg) {
if (!mHasQuit) {
if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);
/** Save the current message */
mMsg = msg;
/** State that processed the message */
State msgProcessedState = null;
//構(gòu)建初始化是否已經(jīng)完成
if (mIsConstructionCompleted) {
//構(gòu)建完成,開始處理狀態(tài)
/** Normal path */
msgProcessedState = processMsg(msg);
//處理完成msgProcessedState,處理完了這個Message以后,將切換到哪個State
} else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
&& (mMsg.obj == mSmHandlerObj)) {
/** Initial one time path. */
//根據(jù)SM_INIT_CMD消息表明構(gòu)建任務(wù)完成,設(shè)置完成標(biāo)志,開始處理消息
mIsConstructionCompleted = true;
//循環(huán)調(diào)用mStateStack中enter方法并將狀態(tài)設(shè)為激活狀態(tài)
invokeEnterMethods(0);
} else {
throw new RuntimeException("StateMachine.handleMessage: "
+ "The start method not called, received msg: " + msg);
}
//msg處理后,做狀態(tài)切換,更新mStateStack
performTransitions(msgProcessedState, msg);
// We need to check if mSm == null here as we could be quitting.
if (mDbg && mSm != null) mSm.log("handleMessage: X");
}
}
狀態(tài)機(jī)構(gòu)建完成,調(diào)用processMsg()處理該狀態(tài),狀態(tài)處理完畢,調(diào)用performTransitions完成狀態(tài)樹的更新
/**
* Process the message. If the current state doesn't handle
* it, call the states parent and so on. If it is never handled then
* call the state machines unhandledMessage method.
*
* 調(diào)用當(dāng)前狀態(tài)處理消息,如果當(dāng)前狀態(tài)沒有處理調(diào)用該狀態(tài)的父狀態(tài)處理,
* 如果最后都沒有處理,調(diào)用unhandledMessage方法
*
* @return the state that processed the message 處理了該消息的狀態(tài)
*/
private final State processMsg(Message msg) {
//獲取棧頂狀態(tài),當(dāng)前所處的狀態(tài)
StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
if (mDbg) {
mSm.log("processMsg: " + curStateInfo.state.getName());
}
if (isQuit(msg)) {
//SM_QUIT_CMD消息,切換到mQuittingState狀態(tài)
transitionTo(mQuittingState);
} else {
//調(diào)用當(dāng)前狀態(tài)機(jī)處理
while (!curStateInfo.state.processMessage(msg)) {
/**
* Not processed
沒有處理調(diào)用父狀態(tài)處理
*/
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());
}
}
}
//返回最后成功處理了Message的那個狀態(tài),如果沒有,那么就是返回null
return (curStateInfo != null) ? curStateInfo.state : null;
}
- 如果接受到是SM_QUIT_CMD消息,切換到mQuittingState狀態(tài),退出狀態(tài)機(jī)
- 調(diào)用當(dāng)前狀態(tài)處理,如果當(dāng)前狀態(tài)沒有處理,沒有處理調(diào)用父狀態(tài)處理
- 如果所有的狀態(tài)都沒有處理該消息,調(diào)用mSm.unhandledMessage
狀態(tài)樹切換
/**
* transition to destination state. Upon returning
* from processMessage the current state's exit will
* be executed and upon the next message arriving
* destState.enter will be invoked.
*
* this function can also be called inside the enter function of the
* previous transition target, but the behavior is undefined when it is
* called mid-way through a previous transition (for example, calling this
* in the enter() routine of a intermediate node when the current transition
* target is one of the nodes descendants).
*
* @param destState will be the state that receives the next message.
*/
protected final void transitionTo(IState destState) {
mSmHandler.transitionTo(destState);
}
/**
* Do any transitions
*
* performTransitions來檢查狀態(tài)切換,為狀態(tài)數(shù)跟新
*
* @param msgProcessedState is the state that processed the message
*/
private void performTransitions(State msgProcessedState, Message msg) {
/**
* If transitionTo has been called, exit and then enter
* the appropriate states. We loop on this to allow
* enter and exit methods to use transitionTo.
*/
State orgState = mStateStack[mStateStackTopIndex].state;
/**
* Record whether message needs to be logged before we transition and
* and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
* always set msg.obj to the handler.
*/
boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
//記錄處理過的消息
if (mLogRecords.logOnlyTransitions()) {
/** Record only if there is a transition */
if (mDestState != null) {
mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState,
orgState, mDestState);
}
} else if (recordLogMsg) {
/** Record message */
mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState,
mDestState);
}
//mDestState,具體狀態(tài)調(diào)用transitionTo(State)時傳入的參數(shù)
//具體狀態(tài)在重寫processMessage時,調(diào)用transitionTo(state)方法,設(shè)置下一步要切換的狀態(tài)
State destState = mDestState;
if (destState != null) {
/**
* Process the transitions including transitions in the enter/exit methods
*/
while (true) {
if (mDbg) mSm.log("handleMessage: new destination call exit/enter");
/**
* Determine the states to exit and enter and return the
* common ancestor state of the enter/exit states. Then
* invoke the exit methods then the enter methods.
*
* 獲取從destState到還沒有active的父節(jié)點(diǎn),
* mTempStateStack存儲是新的終止節(jié)點(diǎn)和
* 舊終止節(jié)點(diǎn)的公共節(jié)點(diǎn)與新的終止節(jié)點(diǎn)的一段狀態(tài)樹
*/
StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
invokeExitMethods(commonStateInfo);
//stateStackEnteringIndex 需要調(diào)用enter方法的狀態(tài)在mStateStack中位置
int stateStackEnteringIndex = moveTempStateStackToStateStack();
//從stateStackEnteringIndex位置開始調(diào)用狀態(tài)棧中state的enter并將active設(shè)為true
invokeEnterMethods(stateStackEnteringIndex);
/**
* Since we have transitioned to a new state we need to have
* any deferred messages moved to the front of the message queue
* so they will be processed before any other messages in the
* message queue.
*
* 轉(zhuǎn)換新狀態(tài)后,將之前的延遲消息移動到消息隊(duì)列的頭部,使得延遲消息的處理早于其他消息
*/
moveDeferredMessageAtFrontOfQueue();
if (destState != mDestState) {
// A new mDestState so continue looping
destState = mDestState;
} else {
// No change in mDestState so we're done
break;
}
}
mDestState = null;
}
/**
* After processing all transitions check and
* see if the last transition was to quit or halt.
*/
if (destState != null) {
if (destState == mQuittingState) {
/**
* Call onQuitting to let subclasses cleanup.
*/
mSm.onQuitting();
cleanupAfterQuitting();
} else if (destState == mHaltingState) {
/**
* Call onHalting() if we've transitioned to the halting
* state. All subsequent messages will be processed in
* in the halting state which invokes haltedProcessMessage(msg);
*/
mSm.onHalting();
}
}
}
- 調(diào)用transitionTo轉(zhuǎn)換狀態(tài),在調(diào)用mSmHandler.transitionTo()設(shè)置目的狀態(tài),當(dāng)消息處理完畢后變調(diào)用performTransitions做真正的狀態(tài)調(diào)整,主要是調(diào)整狀態(tài)棧的節(jié)點(diǎn)信息
- 根據(jù)新的目的節(jié)點(diǎn),調(diào)用setupTempStateStackWithStatesToEnter(),查找到根節(jié)點(diǎn)沒有被激活的狀態(tài),這些節(jié)點(diǎn)存儲在mTempStateStack中,并得到新目的節(jié)點(diǎn)和舊目的節(jié)點(diǎn)公共節(jié)點(diǎn)commonStateInfo
- 根據(jù)commonStateInfo,調(diào)用invokeExitMethods(),將需要移除棧的節(jié)點(diǎn)的狀態(tài)設(shè)為false,并調(diào)用exit方法
- 調(diào)用moveTempStateStackToStateStack將mTempStateStack節(jié)點(diǎn)反轉(zhuǎn)存儲到mStateStack中,這樣當(dāng)前目的節(jié)點(diǎn)位于棧頂,下次處理消息時直接調(diào)用當(dāng)前設(shè)置的目的節(jié)點(diǎn)
- 調(diào)用invokeEnterMethods方法,將新添加的節(jié)點(diǎn)狀態(tài)設(shè)為true,并調(diào)用enter方法
- 在切換狀態(tài)后,如果存在消息沒有處理,調(diào)用moveDeferredMessageAtFrontOfQueue將延遲消息存放在消息隊(duì)列的頭部
狀態(tài)機(jī)的退出
/**
* Quit the state machine after all currently queued up messages are processed.
*/
protected final void quit() {
// mSmHandler can be null if the state machine is already stopped.
SmHandler smh = mSmHandler;
if (smh == null) return;
smh.quit();
}
調(diào)用SmHandler的quit方法
/** @see StateMachine#quit() */
private final void quit() {
if (mDbg) mSm.log("quit:");
sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
}
processMsg處理消息時判斷時退出消息,調(diào)用transitionTo(mQuittingState),切換到QuittingState狀態(tài),做狀態(tài)機(jī)退出工作
具體消息的處理
//藍(lán)牙關(guān)閉狀態(tài)
private class OffState extends State {
@Override
public void enter() {
infoLog("Entering OffState");
}
@Override
public boolean processMessage(Message msg) {
AdapterService adapterService = mAdapterService;
if (adapterService == null) {
errorLog("Received message in OffState after cleanup: " + msg.what);
return false;
}
debugLog("Current state: OFF, message: " + msg.what);
switch(msg.what) {
//初始狀態(tài)是OffState,由OffState處理藍(lán)牙開啟操作
case BLE_TURN_ON:
//通知BluetoothmangerService藍(lán)牙正在開啟
notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
mPendingCommandState.setBleTurningOn(true);
transitionTo(mPendingCommandState);
//發(fā)送延遲消息,檢測打開超時任務(wù)
sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
//批量啟動 profile service
adapterService.BleOnProcessStart();
break;
case USER_TURN_OFF:
//TODO: Handle case of service started and stopped without enable
break;
default:
return false;
}
return true;
}
}
當(dāng)藍(lán)牙關(guān)閉狀態(tài)收到BLE_TURN_ON消息時,表示藍(lán)牙執(zhí)行打開操作,發(fā)出通知表示正在執(zhí)行打開操作,調(diào)用transitionTo將目的狀態(tài)切換到mPendingCommandState,由mPendingCommandState處理后續(xù)的狀態(tài),并開啟打開任務(wù)的超時檢測;調(diào)用BleOnProcessStart,啟動所需要的藍(lán)牙服務(wù);服務(wù)啟動后通過StateMachine的sendMessage()會發(fā)送BLE_STARTED消息,mSmHandler調(diào)用processMsg(),該消息由mPendingCommandState處理。
總結(jié)
StateMachine在初始化時會創(chuàng)建一個HandleThread,用來處理維護(hù)消息隊(duì)列。
通過addState方法創(chuàng)建一個層次狀體樹,所有這些節(jié)點(diǎn)將存儲在HashMap<State,StateInfo> mStateInfo中,
調(diào)用setInitialState方法設(shè)置初始狀態(tài);調(diào)用start方法開始創(chuàng)建狀態(tài)棧,使得初始狀態(tài)位于棧頂,這樣處理消息時,直接交給棧頂節(jié)點(diǎn)處理。狀態(tài)棧構(gòu)建完成將所有棧中的節(jié)點(diǎn)設(shè)為true,并執(zhí)行enter方法,表示狀態(tài)可以進(jìn)入工作。然后向狀態(tài)機(jī)發(fā)送SM_INIT_CMD消息,由狀態(tài)機(jī)處理該消息。如果狀態(tài)機(jī)構(gòu)建完成,這是消息由當(dāng)前的節(jié)點(diǎn)處理,如果當(dāng)前節(jié)點(diǎn)不能處理交由父節(jié)點(diǎn)處理,所有節(jié)點(diǎn)都不能處理處理,調(diào)用狀態(tài)機(jī)的unhandledMessage方法(這個方法一般由具體狀態(tài)機(jī)實(shí)現(xiàn)),消息處理了返回true,沒有處理返回false。
如果在處理消息時調(diào)用transitionTo設(shè)置新目的狀態(tài),消息處理完成后,performTransition方法會設(shè)置調(diào)整狀態(tài)棧的節(jié)點(diǎn)信息,這樣新的節(jié)點(diǎn)設(shè)置在棧頂,消息來消息時直接調(diào)用棧中取出,處理消息。
推出狀態(tài)機(jī)調(diào)用quit或quitNow,向狀態(tài)機(jī)發(fā)送SM_QUIT_CMD消息,處理后續(xù)的事情。
備注
源代碼使用androud_6.0.1_r1
注釋代碼