安卓StateMachine学习笔记--待续

来源:互联网 发布:华东理工大学网络教育 编辑:程序博客网 时间:2024/05/20 07:36

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退出流程中已经对这个方法进行了分析。

0 0
原创粉丝点击