StateMachine与State模式的详细介绍可以参考文章:Android学习 StateMachine与State模式
下面是我对于StateMachine的理解:
先了解下消息处理。看下StateMachine::sendMessage方法。
不管BT/Wifi中,都有继承StateMachine的子类(BluetoothAdapterStateMachine.java/WifiStateMachine.java),在某些类中,会创建这些类的对象,当需要发送消息时,会调用它们的sendMessage方法,即调用父类StateMachine的sendMessage方法。
/** * Enqueue a message to this state machine. */ public final void sendMessage(int what) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; mSmHandler.sendMessage(obtainMessage(what)); } /** * Enqueue a message to this state machine. */ public final void sendMessage(int what, Object obj) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; mSmHandler.sendMessage(obtainMessage(what,obj)); } /** * Enqueue a message to this state machine. */ public final void sendMessage(Message msg) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; mSmHandler.sendMessage(msg); }
从sendMessage方法中可以看到,实际上是调用了StateMachine::SmHandler::sendMessage方法,该类没有实现该方法,所以会调用父类Handler::sendMessage方法,然后会调用StateMachine::SmHandler::handleMessage方法进行处理:
/** * 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. */ @Override public final void handleMessage(Message msg) { if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what); /** Save the current message */ mMsg = msg; if (mIsConstructionCompleted) { /** Normal path */ processMsg(msg); //1 } else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) { /** Initial one time path. */ mIsConstructionCompleted = true; invokeEnterMethods(0); } else { throw new RuntimeException("StateMachine.handleMessage: " + "The start method not called, received msg: " + msg); } performTransitions(); //2 if (mDbg) Log.d(TAG, "handleMessage: X"); }
该方法中有两个重要的方法:
1.processMsg(msg);
/** * 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. */ private final void processMsg(Message msg) { StateInfo curStateInfo = mStateStack[mStateStackTopIndex]; if (mDbg) { Log.d(TAG, "processMsg: " + curStateInfo.state.getName()); } while (!curStateInfo.state.processMessage(msg)) { /** * Not processed */ curStateInfo = curStateInfo.parentStateInfo; if (curStateInfo == null) { /** * No parents left so it's not handled */ mSm.unhandledMessage(msg); if (isQuit(msg)) { transitionTo(mQuittingState); } break; } if (mDbg) { Log.d(TAG, "processMsg: " + curStateInfo.state.getName()); } } /** * Record that we processed the message */ if (mSm.recordProcessedMessage(msg)) { if (curStateInfo != null) { State orgState = mStateStack[mStateStackTopIndex].state; mProcessedMessages.add(msg, mSm.getMessageInfo(msg), curStateInfo.state, orgState); } else { mProcessedMessages.add(msg, mSm.getMessageInfo(msg), null, null); } } }
这个方法中有一个while循环,看下条件:curStateInfo.state.processMessage(msg),即调用当前状态(State具体的子类)的processMessage方法。在具体实现的State子类中,在processMessage方法中,在具体的case处理完message后,会返回true 或 false(true的话会使得上述代码中的while循环退出,即该消息不上传给父状态处理,自己处理完就好了;false的话,就是再上传给父状态处理)。
2.performTransitions();
/** * Do any transitions */ private void performTransitions() { /** * 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 destState = null; while (mDestState != null) { if (mDbg) Log.d(TAG, "handleMessage: new destination call exit"); /** * Save mDestState locally and set to null * to know if enter/exit use transitionTo. */ destState = mDestState; mDestState = null; /** * 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. */ StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState); invokeExitMethods(commonStateInfo); int stateStackEnteringIndex = moveTempStateStackToStateStack(); 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. */ moveDeferredMessageAtFrontOfQueue(); } /** * After processing all transitions check and * see if the last transition was to quit or halt. */ if (destState != null) { if (destState == mQuittingState) { cleanupAfterQuitting(); } else if (destState == mHaltingState) { /** * Call halting() if we've transitioned to the halting * state. All subsequent messages will be processed in * in the halting state which invokes haltedProcessMessage(msg); */ mSm.halting(); } } }
这个方法主要是完成:
1.当前状态的切换,
2.更新状态栈。
比如状态已经通过addState方法添加完毕,形成了树形结构。当前状态是S4,现在要切换到S5。performTransitions方法中会完成一项功能:pop S4 S1,push S2 S5。