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。

Android stateMachine分析的更多相关文章

  1. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  2. Android多线程分析之四:MessageQueue的实现

    Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...

  3. Android多线程分析之三:Handler,Looper的实现

    Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...

  4. Android多线程分析之二:Thread的实现

    Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处   在前文<Android多线程分析之一 ...

  5. Android多线程分析之一:使用Thread异步下载图像

    Android多线程分析之一:使用Thread异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处   打算整理一下对 Android F ...

  6. Android Launcher分析和修改13——实现Launcher编辑模式(1) 壁纸更换

    已经很久没更新Launcher系列文章,今天不分析源码,讲讲如何在Launcher里面添加桌面设置的功能.目前很多第三方Launcher或者定制Rom都有简单易用的桌面设置功能.例如小米MIUI的La ...

  7. Android Launcher分析和修改9——Launcher启动APP流程

    本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务.客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题.没办法,只能看看是怎么 ...

  8. 正确使用Android性能分析工具——TraceView

    http://blog.jobbole.com/78995/     首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他技术 - 导航条 - 首页 最新文章 IT 职场 前端 - Ja ...

  9. Android架构分析之Android消息处理机制(二)

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的样例,本文我们 ...

随机推荐

  1. Java数据结构的实现

    1.基于数组的链表 package array; import java.util.Arrays; /** * 基于数组的链表 * * @author 王彪 * */ public class MyA ...

  2. Java的内存--存储(1)

    有次去面试,面试官突然问我这个问题,当时我只知道怎么写最优化,但是具体不知道为什么那样写,身价立马下降哦 1. 以下开发习惯,你怎么看? for(int i=0;i<2;i++){ Person ...

  3. [国家集训队]小Z的袜子(莫队,概率)

    题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编 ...

  4. Lucas定理及应用

    额,前两天刚讲了数据结构,今天我来讲讲组合数学中的一种奇妙优化——Lucas 先看这样一个东西 没学过lucas的肯定会说:还不简单?处理逆元,边乘边膜呗 是,可以,但注意一下数据范围 你算这一次,你 ...

  5. 使用 form 和 iframe 实现图片上传回显

    主要利用 form 的 target 属性,在提交表单之后 response 返回到 iframe 中 form 的 action 可以自己写,也可以直接利用 富文本编辑器的接口实现上传 <fo ...

  6. mysql5.7 本地计算机上的mysql 服务启动后停止 的问题解决

    mysql5.7 本地计算机上的mysql 服务启动后停止. 问题: 在cmd 下mysql服务mysql服务无法启动任何错误法启动 服务没有报告任何错误     在服务里面启动是   早上来了发现项 ...

  7. springmvc的类型转换器converter

    这个convter类型转换是器做什么用的? 他是做类型转换的,或者数据格式化处理.可以把数据在送到controller之前做处理.变成你想要的格式或者类型.方便我们更好的使用. 比如说你从前台传过来一 ...

  8. what is feeding and what is 读扩散 and 写扩散?

    what is feeding? 通俗点说feed系统就是当你登陆进对应网站后:微信朋友圈的动态.人人网上看到的一件件新鲜事.新浪微博上推到你面前的一条条新围脖等等.系统中的每一条消息就是一个feed ...

  9. QQ运动,新楛的马桶还在香,营销人不应摒弃。

    QQ运动,都说新楛的马桶还香三天,为毛你这般明日黄花,为营销人所弃. QQ运动,一个差不多被遗忘的冷却地带,却圈粉无数,以性感.狂野.妖艳.线条.汗水等秀元素贯穿始终,狼友显露于此,爱美的女性也未曾缺 ...

  10. centos编译安装rabbitmq

    安装环境 [root@VM_12_50_centos rabbitmq]# uname -a Linux VM_12_50_centos 3.10.0-514.21.1.el7.x86_64 #1 S ...