StateMachine类的初始化:
通过StateMachine的构造类进行构造.在构造函数中:
根据状态机的名字创建一个mSmThread线程并启动(此线程待分析).
创建一个looper对象,并传给SmHandler构造出mSmHandler(此对象待分析)
SmHandler对象构造时,与状态机对象关联,并给SmHandler加入内部状态mHaltingState,mQuittingState(这两个对象待分析)
mSmThread线程的启动:
mSmThread线程启动后,进入run方法进入线程主体:
通过Looper.prepare()中创建一个Looper对象,Looper中创建MessageQueue消息队列对象.
调用Looper.loop方法进入循环从消息队列中获取消息,并进行消息分发及处理,最后进行消息回收.
loop()代码:
for (;;) {
Message msg = queue.next(); // might block
msg.target.dispatchMessage(msg)
msg.recycle();
}
其中,处理消息时,调用的是发送消息时传入的target对象的dispatchMessage方法;
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
StateMachine的启动:
通过start方法启动状态机, 在completeConstruction中,开始对状态机的状态栈进行初始化. 栈的深度由状态树的最大深度决定:
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;
}
mStateStack = new StateInfo[maxDepth];
mTempStateStack = new StateInfo[maxDepth];
}
根据mInitialState初始,构建临时栈数据临mTempStateStack.
StateInfo curStateInfo = mStateInfo.get(mInitialState);
for (mTempStateStackCount = 0; curStateInfo !=null;mTempStateStackCount++) {
mTempStateStack[mTempStateStackCount] = curStateInfo;
curStateInfo = curStateInfo.parentStateInfo;
}
在moveTempStateStackToStateStack方法中,将mTempStateStack倒置复制给mStateStack
mStateStackTopIndex 记录初始状态的位置,
int startingIndex = mStateStackTopIndex + 1;
int i = mTempStateStackCount - 1;
int j = startingIndex;
while (i >= 0) {
mStateStack[j] = mTempStateStack[i];
j += 1;
i -= 1;
}
mStateStackTopIndex = j - 1;
状态机栈创建成功后,发送SM_INIT_CMD消息, 此消息在SmHandler类的 handleMessage方法中被处理.(根据之前消息处理函数的逻辑,当前smhandler没有注册消息的回调,所以调用smhandler重写的handleMessage方法进行消息处理)
public final void handleMessage(Message msg) {
.......
else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
&& (mMsg.obj == mSmHandlerObj)) {
/* 状态机启动后,受到初始化消息后, */
mIsConstructionCompleted = true;
invokeEnterMethods(0);
} else {
}
performTransitions(msgProcessedState, msg);
}
}
对于启动消息SM_INIT_CMD的处理,重点做两件事情:
1.invokeEnterMethods中,执行状态栈中状态的enter方法,这里是从init状态的祖先依次运行到init状态自身的enter方法,启动相关的处理一般都可以在init或者init状态的祖先状态中找:
private final void invokeEnterMethods(int stateStackEnteringIndex) {
for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
mStateStack[i].state.enter();
mStateStack[i].active = true;
}
}
2.performTransitions(msgProcessedState, msg),在处理启动消息时,不做事情。
StateMachine的退出:
通过调用StateMachine类的quit方法实现状态机退出。也可以通过quitNow进行立即退出。
quit方法发送SM_QUIT_CMD消息,smhander在processMsg函数处理此消息:跳转状态到mQuittingState
private final State processMsg(Message msg) {
/*省略代码*/
if (isQuit(msg)) {
transitionTo(mQuittingState);
}
/*省略代码*/
}
然后通过performTransitions进行状态转移操作:如果是退出消息,则进入mQuittingState状态,触发mSm.onQuitting,并清理资源cleanupAfterQuitting。
private void performTransitions(State msgProcessedState, Message msg) {
State orgState = mStateStack[mStateStackTopIndex].state;
State destState = mDestState;
if (destState != null) {
while (true) {
/*沿着家谱寻找目标状态激活的祖先状态,并构建临时状态栈mTempStateStack*/
StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
/*沿着状态机栈从顶向下寻找搜虚这个祖先状态,找不到就将状态依次退栈mStateStack,并执行状态的退出方法exit,并将相应的状态置为非激活状态*/
invokeExitMethods(commonStateInfo);
/*将临时堆栈mTempStateStack的信息,加入到mStateStack*/
int stateStackEnteringIndex = moveTempStateStackToStateStack();
/*自底部向上依次触发补充入桟的状态的enter方法*/
invokeEnterMethods(stateStackEnteringIndex);
/*将deferred队列中的消息转发到消息队列前部*/
moveDeferredMessageAtFrontOfQueue();
if (destState != mDestState) {
destState = mDestState;
} else {
break;
}
}/*end of while*/
mDestState = null;
}/*end of if (destState != null) */
if (destState != null) {
if (destState == mQuittingState) {
mSm.onQuitting();
cleanupAfterQuitting();
} else if (destState == mHaltingState) {
haltedProcessMessage(msg);
mSm.onHalting();
}
}
}
状态机启动成功后消息处理:
状态机启动成功后,消息处理的工作交接给processMsg
if (mIsConstructionCompleted) {
msgProcessedState = processMsg(msg);
}
在processMsg方法中,处理非quitmsg的流程如下:
/*获取当前的状态*/
StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
if (isQuit(msg)) {
transitionTo(mQuittingState);
} else {
/*调用当前状态的处理消息函数处理消息*/
while (!curStateInfo.state.processMessage(msg)) {
/*如果当前状态没有处理消息,则移交给父状态处理*/
curStateInfo = curStateInfo.parentStateInfo;
/*如果父状态不存在,则消息流失退出处理*/
if (curStateInfo == null) {
mSm.unhandledMessage(msg);
break;
}
}
}
处理完消息后,调用performTransitions做下状态的记录,以及状态转换,如果有状态切换,则在此处完成处理。StateMachine退出流程中已经对这个方法进行了分析。