Android状态机源码分析
来源:互联网 发布:南昌小目标网络 编辑:程序博客网 时间:2024/06/06 02:22
转载自:http://blog.csdn.net/yangwen123/article/details/10591451
在Android系统中,经常使用状态机来处理不同状态下的行为动作。状态机是将对象的状态与行为封装在一起;可以解决庞大的分支语句带来程序阅读性差和不便于进行扩展问题,使整个结构变得更加清晰明了,降低程序管理的复杂性提高灵活度。Android系统的StateMachine机制是一个State模式的应用,StateMachine是一个分层处理消息的状态机,并且是能够有分层排列状态。
构造状态机
StateMachine的构造函数都是protected类型,不能实例化,都是由其子类进行初始化操作。StateMachine有两个重载的构造函数,一个是通过指定消息循环对象来构造状态机
- protected StateMachine(String name, Looper looper) {
- initStateMachine(name, looper);
- }
另一个则是直接启动一个消息循环线程来构造一个状态机
- protected StateMachine(String name) {
- //启动一个消息循环线程
- mSmThread = new HandlerThread(name);
- mSmThread.start();
- Looper looper = mSmThread.getLooper();
- initStateMachine(name, looper);
- }
- private void initStateMachine(String name, Looper looper) {
- mName = name;
- mSmHandler = new SmHandler(looper, this);
- }
状态机中的每个状态使用State来封装,对于每个状态的信息又采用StateInfo来描述
StateMachine三个内部类:
1.ProcessedMessageInfo:保存已处理消息的信息;
2.ProcessedMessages:存储StateMachine最近处理的一些消息,需要保存最近处理的消息条数默认20,可以用户自己设定最大数目;
3.SmHandle是消息处理派发和状态控制切换的核心,运行在单独的线程上;
SmHandle成员变量定义:
ProcessedMessages用于保存已处理过的消息,mStateStack和mTempStateStack是一个数组栈,用于保存状态机中的链式状态关系。
mStateInfo定义为一个Hash链表,用于保存添加的所有状态。mInitialState保存初始状态,mDestState保存切换的目的状态。
建立树形层次结构状态机
- protected final void addState(State state, State parent) {
- mSmHandler.addState(state, parent);
- }
- private final StateInfo addState(State state, State parent) {
- if (mDbg) {
- Log.d(TAG, "addStateInternal: E state=" + state.getName()
- + ",parent=" + ((parent == null) ? "" : parent.getName()));
- }
- StateInfo parentStateInfo = null;
- if (parent != null) {
- parentStateInfo = mStateInfo.get(parent);
- if (parentStateInfo == null) {
- // Recursively add our parent as it's not been added yet.
- parentStateInfo = addState(parent, null);
- }
- }
- StateInfo stateInfo = mStateInfo.get(state);
- if (stateInfo == null) {
- stateInfo = new StateInfo();
- mStateInfo.put(state, stateInfo);
- }
- // Validate that we aren't adding the same state in two different hierarchies.
- if ((stateInfo.parentStateInfo != null) &&
- (stateInfo.parentStateInfo != parentStateInfo)) {
- throw new RuntimeException("state already added");
- }
- stateInfo.state = state;
- stateInfo.parentStateInfo = parentStateInfo;
- stateInfo.active = false;
- if (mDbg) Log.d(TAG, "addStateInternal: X stateInfo: " + stateInfo);
- return stateInfo;
- }
- sm.addState(S0,null);
- sm.addState(S1,S0);
- sm.addState(S2,S0);
- sm.addState(S3,S1);
- sm.addState(S4,S1);
- sm.addState(S5,S2);
- sm.addState(S6,S2);
- sm.addState(S7,S2);
- setInitialState(S4); //设置初始状态
- private final StateInfo addState(S0,null)
- {
- StateInfo parentStateInfo = null;
- //状态S0还未加入状态机中
- StateInfo stateInfo = mStateInfo.get(state);
- if (stateInfo == null) {
- //创建State详细信息对象
- stateInfo = new StateInfo();
- //将S0加入状态机中
- mStateInfo.put(state, stateInfo);
- }
- //设置状态S0的状态信息
- stateInfo.state = state;
- //S0的父节点为null
- stateInfo.parentStateInfo = parentStateInfo;
- stateInfo.active = false;
- return stateInfo;
- }
- private final StateInfo addState(State state, State parent)
- {
- StateInfo parentStateInfo = null;
- //状态S0在前面已经加入状态机中了
- if (parent != null) {
- //获取S0详细信息 StateInfo
- parentStateInfo = mStateInfo.get(parent);
- //因为S0已经存在于状态机中,因此这里不为空
- if (parentStateInfo == null) {
- //当前状态父状态未加入到StateMachine中,递归先加入其父State
- parentStateInfo = addState(parent, null);
- }
- }
- //从状态机中得到S1的状态信息,由于S1还为加入状态机,因此得到的结果为空
- StateInfo stateInfo = mStateInfo.get(state);
- if (stateInfo == null) {
- //创建State详细信息对象
- stateInfo = new StateInfo();
- //将S1加入状态机中
- mStateInfo.put(state, stateInfo);
- }
- //S1的状态信息刚创建,还没有为其设置父节点,因此其父节点为空
- if ((stateInfo.parentStateInfo != null) &&
- (stateInfo.parentStateInfo != parentStateInfo)) {
- throw new RuntimeException("state already added");
- }
- //设置状态S1的状态信息
- stateInfo.state = state;
- //S1的父节点为S0
- stateInfo.parentStateInfo = parentStateInfo;
- stateInfo.active = false;
- return stateInfo;
- }
启动状态机
- public void start() {
- // mSmHandler can be null if the state machine has quit.
- if (mSmHandler == null) return;
- /** Send the complete construction message */
- mSmHandler.completeConstruction();
- }
- private final void completeConstruction() {
- if (mDbg) Log.d(TAG, "completeConstruction: E");
- //查找状态树的深度
- 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) Log.d(TAG, "completeConstruction: maxDepth=" + maxDepth);
- //创建mStateStack,mTempStateStack状态栈
- mStateStack = new StateInfo[maxDepth];
- mTempStateStack = new StateInfo[maxDepth];
- //设置状态堆栈
- setupInitialStateStack();
- /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
- sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
- if (mDbg) Log.d(TAG, "completeConstruction: X");
- }
- private final void setupInitialStateStack() {
- //在mStateInfo中取得初始状态mInitialState对应的StateInfo
- StateInfo curStateInfo = mStateInfo.get(mInitialState);
- //从初始状态mInitialState开始根据父子关系填充mTempStateStack堆栈
- for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
- mTempStateStack[mTempStateStackCount] = curStateInfo;
- curStateInfo = curStateInfo.parentStateInfo;
- }
- // Empty the StateStack
- mStateStackTopIndex = -1;
- //将mTempStateStack中的状态按反序方式移动到mStateStack栈中
- moveTempStateStackToStateStack();
- }
mTempStateStackCount = 3;
- private final int moveTempStateStackToStateStack() {
- //startingIndex= 0
- int startingIndex = mStateStackTopIndex + 1;
- int i = mTempStateStackCount - 1;
- int j = startingIndex;
- while (i >= 0) {
- if (mDbg) Log.d(TAG, "moveTempStackToStateStack: i=" + i + ",j=" + j);
- mStateStack[j] = mTempStateStack[i];
- j += 1;
- i -= 1;
- }
- mStateStackTopIndex = j - 1;
- return startingIndex;
- }
初始化完状态栈后,SmHandler将向消息循环中发送一个SM_INIT_CMD消息
- sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj))
- else if (!mIsConstructionCompleted &&(mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {
- mIsConstructionCompleted = true;
- invokeEnterMethods(0);
- }
- performTransitions();
- private final void invokeEnterMethods(int stateStackEnteringIndex) {
- for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
- if (mDbg) Log.d(TAG, "invokeEnterMethods: " + mStateStack[i].state.getName());
- mStateStack[i].state.enter();
- mStateStack[i].active = true;
- }
- }
状态切换
- private synchronized void performTransitions() {
- while (mDestState != null){
- //当前状态切换了 存在于mStateStack中的State需要改变
- //仍然按照链式父子关系来存储
- //先从当前状态S3找到 最近的被激活的parent状态S0
- //未被激活的全部保存起来(S3,S1) 返回S0
- StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
- //将mStateStack中 不属于当前状态(S3),
- //关系链上的State(S5,S2)退出(执行exit方法)
- invokeExitMethods(commonStateInfo);
- //将S3关系链 加入到栈中(S3,S1)
- int stateStackEnteringIndex = moveTempStateStackToStateStack();
- //将新加入到mStateStack中 未被激活的State激活(S3,S1)
- invokeEnterMethods(stateStackEnteringIndex);
- //将延迟的消息移动到消息队列的前面,以便快速得到处理
- moveDeferredMessageAtFrontOfQueue();
- }
- }
以上图中,初始状态为S4,现在目标状态mDestState被设置为S7。前面介绍了保存在mStateStack数组中的节点为:
- private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
- mTempStateStackCount = 0;
- StateInfo curStateInfo = mStateInfo.get(destState);
- do {
- mTempStateStack[mTempStateStackCount++] = curStateInfo;
- if (curStateInfo != null) {
- curStateInfo = curStateInfo.parentStateInfo;
- }
- } while ((curStateInfo != null) && !curStateInfo.active);
- return curStateInfo;
- }
- private final void invokeExitMethods(StateInfo commonStateInfo) {
- while ((mStateStackTopIndex >= 0) &&
- (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
- State curState = mStateStack[mStateStackTopIndex].state;
- if (mDbg) Log.d(TAG, "invokeExitMethods: " + curState.getName());
- curState.exit();
- mStateStack[mStateStackTopIndex].active = false;
- mStateStackTopIndex -= 1;
- }
- }
- private final int moveTempStateStackToStateStack() {
- //startingIndex= 0
- int startingIndex = mStateStackTopIndex + 1;
- int i = mTempStateStackCount - 1;
- int j = startingIndex;
- while (i >= 0) {
- if (mDbg) Log.d(TAG, "moveTempStackToStateStack: i=" + i + ",j=" + j);
- mStateStack[j] = mTempStateStack[i];
- j += 1;
- i -= 1;
- }
- mStateStackTopIndex = j - 1;
- return startingIndex;
- }
- private final void invokeEnterMethods(int stateStackEnteringIndex) {
- for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
- if (mDbg) Log.d(TAG, "invokeEnterMethods: " + mStateStack[i].state.getName());
- mStateStack[i].state.enter();
- mStateStack[i].active = true;
- }
- }
- protected final void transitionTo(IState destState) {
- mSmHandler.transitionTo(destState);
- }
- private final void transitionTo(IState destState) {
- mDestState = (State) destState;
- if (mDbg) Log.d(TAG, "transitionTo: destState=" + mDestState.getName());
- }
消息处理
StateMachine处理的核心就是SmHandler,就是一个Handler,运行在单独线程中。Handler是用来异步处理派发消息,这里使用Handler管理各个状态,派发消息处理到各个状态中去执行。StateMachine提供了多个消息发送接口,通过这些接口函数可以将消息发送到SmHandler中。
- public final void sendMessage(int what) {
- // mSmHandler can be null if the state machine has quit.
- if (mSmHandler == null) return;
- mSmHandler.sendMessage(obtainMessage(what));
- }
- public final void handleMessage(Message msg) {
- /** Save the current message */
- mMsg = msg;
- if (mIsConstructionCompleted) {
- //派发当前消息到state中去处理
- processMsg(msg);
- } 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);
- }
- //消息处理完毕更新mStateStack
- performTransitions();
- }
- private final void processMsg(Message msg) {
- StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
- //如果当前状态未处理该消息
- while (!curStateInfo.state.processMessage(msg)) {
- //将消息传给当前状态的父节点处理
- curStateInfo = curStateInfo.parentStateInfo;
- if (curStateInfo == null) {
- //当前状态无父几点,则丢弃该消息
- mSm.unhandledMessage(msg);
- if (isQuit(msg)) {
- transitionTo(mQuittingState);
- }
- break;
- }
- }
- //记录处理过的消息
- 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);
- }
- }
- }
- Android状态机源码分析
- Android状态机源码分析
- Android状态机源码分析
- Android蓝牙源码分析——StateMachine状态机
- Lighttpd1.4.20源码分析之状态机(1)---状态机总览
- Memcached源码分析之状态机(一)
- Memcached源码分析之状态机(二)
- Memcached源码分析之状态机(三)
- Lighttpd源码分析之状态机与插件
- Harbor 源码分析之状态机(五)
- Lighttpd源码分析之状态机与插件
- DSS源码分析--对RTSP请求的状态机处理机制
- rstplib源码分析---快速生成树之端口信息状态机
- rstplib源码分析---快速生成树之拓扑变化状态机
- rstplib源码分析---快速生成树之通用状态机
- memcached 源码分析之请求处理(状态机)
- Lighttpd1.4.20源码分析 笔记 状态机与插件
- Lighttpd1.4.20源码分析 笔记 状态机之请求处理
- 1、不一样的C++系列--C到C++的升级
- POJ2674-Linear world
- android p2p 学习
- Linux--重定向dup&&dup2
- Q109:用PBRT渲染Blender导出的模型 (2)
- Android状态机源码分析
- hdu 1007 解法
- openvpn实现内网 映射到 外网
- 实现 QPushButton 默认效果
- 关于hdu 1007 老是 TLE的认知
- ARM开发板开发基础
- JAVA模拟实现Windows屏保/实现JFrame窗口透明到桌面
- FCN中反卷积、上采样、双线性插值之间的关系
- Spring 04 AOP