安卓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退出流程中已经对这个方法进行了分析。
- 安卓StateMachine学习笔记--待续
- Android StateMachine 学习笔记
- 安卓StateMachine分析举例---WifiStateMachine
- 疯狂安卓书籍的学习--未完待续~
- 项目学习笔记(待续......)
- oracle学习笔记,待续~
- 深度学习笔记(待续)
- 安卓StateMachine运行过程理解(翻译)
- 安卓学习笔记
- 安卓学习笔记
- 安卓学习笔记
- 安卓学习笔记
- 安卓学习笔记
- 安卓学习笔记
- 安卓学习笔记
- GDI+学习笔记(待续)
- SQL学习笔记(待续)
- vim学习笔记(待续...)
- hdoj function 5608 (数学)
- HDU 5606 Tree(连通块)
- <C>Josephus问题——用循环链表解决
- golang database 全局
- <LeetCode OJ> 189. Rotate Array
- 安卓StateMachine学习笔记--待续
- 4.虚拟机ubuntu网络问题汇总
- PHP搭建自己的web框架-程序初始化
- iOS音频开发
- malloc free new delete 赋值构造函数相关使用及区别
- Angularjs + Requirejs 完整的手脚架
- MD5Util开发工具类
- 一些相关概念
- linux下的用户管理小结