android状态机statemachine详解
分类:android应用分析 2013-08-13 07:18 1749人阅读 评论(1) 收藏 举报 android状态机详解 statemachine android 状态state
先说两句题外话,很感谢android,在这里能看到很多优秀的代码。同时也感觉到外面的工程师真的很厉害,都是java人家就能写出这么牛的东西。感慨之下就有了些思考:我们绝大多数人只要把那些牛人已经创造出来的牛逼的东西,记住并且弄懂就是一件非常不错的事情,至少能衣食无忧。:-D 读书的时候需要经常做题,在理解的基础上记住解题方法基本就能很牛了,事实上高考中考绝大多数都是已经有过的题型,能做到前面所说的应该能进入不错的学校。工作后,慢慢也发现很多了不起的技术,都是在国外已经发展的很成熟基础上学习过来的。作为一个普通人,还是不要天天谈创新的好,hold不住,把基础的东西记住掌握即可。说了一堆,也算聊以自慰。
我们知道类的成员可以分为两种:方法和属性。大多数情况下,对于一个状态,比如某数大于0,类的方法都只能做出一种对应的操作,并且类的本身并不考虑外部状态。android的状态机就属于大多数之后的那一小部分。对于某个事件,或者更准确的说,某一个消息,在不同的状态下能做出不同的操作。并且android状态机中的状态是继承的,就像数据结构中的树一样,如果当前节点(状态)不能对这个事件做出响应,就会到父节点继续判断并且做出响应,在下面的讲述中,我们称这个为状态路径,而对于所有状态称为状态树。这一句话已经从整体上对状态机进行了概括,记住这些对后面的理解很有好处。
State,状态机中的状态封装类,这个类主要是实现了IState接口。其中有状态的基本方法,enter,exit以及消息处理方法processMessage。enter方法在状态机转入这个状态中会进行调用,exit方法在状态机转出这个方法时候会调用。这里对于一个很简单的类,google使用了接口属性,说说自己的理解。接口中的方法都是公有方法,并且只能声明常量。将主要方法都放在接口中声明,一方面限制了方法的定义,一方面也突出了这个类主要就是拥有某种功能。另外在State里面,声明了一个protect类型的构造方法,这样其他类就不可以直接声明state类的对象。state在状态机statemachine类里面是以StateInfo类型使用的,这个基本不影响访问。
statemachine里面主要工作都是由SmHandler类来完成的,statemachine本身绝大多数方法都是都是对SmHandler方法的再次封装。另外为了能够做到及时响应主线程的消息,又声明了一个HandlerThread,主要任务都是在这个线程里面实现的。
现在直接去看SmHandler类吧,其最主要的方法就是handleMessage。该方法的主要是三大模块,第一个消息处理,或者说是分配到对应的状态再有对应的状态进行处理比较合适,第二个状态的初始化,大概可以理解成执行初始化状态路径上每个状态的enter方法,第三个执行状态转移,即更新状态树。
- if(mIsConstructionCompleted){
- /**Normalpath*/
- processMsg(msg);//第一个消息处理
- }elseif(!mIsConstructionCompleted&&
- (mMsg.what==SM_INIT_CMD)&&(mMsg.obj==mSmHandlerObj)){
- /**Initialonetimepath.*/
- mIsConstructionCompleted=true;
- invokeEnterMethods(0);//第二个状态的初始化
- }else{
- thrownewRuntimeException("StateMachine.handleMessage:"+
- "Thestartmethodnotcalled,receivedmsg:"+msg);
- }
- performTransitions();//第三个执行状态转移
首先去看下processMsg方法
[java] view plain copy print ?- while(!curStateInfo.state.processMessage(msg)){
- /**
- *Notprocessed
- */
- curStateInfo=curStateInfo.parentStateInfo;
- if(curStateInfo==null){
- /**
- *Noparentsleftsoit'snothandled
- */
- mSm.unhandledMessage(msg);
- break;
- }
- if(mDbg){
- Log.d(TAG,"processMsg:"+curStateInfo.state.getName());
- }
- }
从这段代码中(!curStateInfo.state.processMessage(msg))就说明了:如果当前状态执行完processMessage方法返回了false,也就是对当前消息NOT_HANDLED,那么就会持续调用这个状态的父状态执行方法。一般终有一个状态能够处理消息的,如果真的没有处理,会记录到unhandledMessage方法里面的。
接下来先看下状态转移performTransitions方法,首先碰到mDestState,这是SmHandler里面的一个标记,指向当前状态路径最下面的一个状态,后面都是父状态。可以在其他时候调用private final void transitionTo(IState destState)方法(外面的接口方法)改变当前mDestState的指向。这样处理完当前消息之后,performTransitions就会根据最新的mDestState来进行状态路径切换。状态切换有点像树的遍历一样,并不是回到根节点在进行搜索到新的节点,而是会回到原来的mDestState和最新的mDestState最近的一个共同祖先,然后在走向新的mDestState状态。进行状态切换主要是执行原状态路径上需要退出的状态的exit()方法,和新的状态路径上的enter()方法。
最后看下状态机的初始化invokeEnterMethods,这个直接看状态机的实例比较方便。看一个简单一些的应用,蓝牙APK里面关于耳机和电话连接处理的HeadsetStateMachine类,其构造方法中,关于状态机的代码如下:
- addState(mDisconnected);
- addState(mPending);
- addState(mConnected);
- addState(mAudioOn);
- setInitialState(mDisconnected);
以上两块代码,第一块是建立本状态机的整个框架,就相当于建立整个状态树,第二个是设置初始化状态。再看看HeadsetStateMachine中的静态代码块
[java] view plain copy print ?- staticHeadsetStateMachinemake(HeadsetServicecontext){
- Log.d(TAG,"make");
- HeadsetStateMachinehssm=newHeadsetStateMachine(context);
- hssm.start();
- returnhssm;
- }
以上两块代码,第一块是建立本状态机的整个框架,就相当于建立整个状态树,第二个是设置初始化状态。再看看HeadsetStateMachine中的静态代码块
这里面有一个start()方法,从这个方法开始,状态机开始运作,包括分配内存,根据初始化状态设置初始化状态路径,这一点主要在setupInitialStateStack方法中执行,依次执行状态路径上每个状态的enter方法,这个使用了消息机制sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));,最终就在本段开头的invokeEnterMethods方法中执行。
到这里状态机主要内容基本讲解完毕,貌似绝大多数都需要记忆,记住了感觉就理解到了。:-D 有点像本文开头说的。初一看感觉没有什么,但是如果想象下你有一个这样的需求,耳机和手机的状态一直在切换,你会采用什么方式去做,在考虑了很多之后会感觉状态机真的是一个很厉害的东西。:-D 接下来附上android源码中的demo,为了方便理解,笔者将输出增加了一些空行,多余的空行不是demo打印的。
- classHsm1extendsStateMachine{
- privatestaticfinalStringTAG="hsm1";
- publicstaticfinalintCMD_1=1;
- publicstaticfinalintCMD_2=2;
- publicstaticfinalintCMD_3=3;
- publicstaticfinalintCMD_4=4;
- publicstaticfinalintCMD_5=5;
- publicstaticHsm1makeHsm1(){
- Log.d(TAG,"makeHsm1E");
- Hsm1sm=newHsm1("hsm1");
- sm.start();
- Log.d(TAG,"makeHsm1X");
- returnsm;
- }
- Hsm1(Stringname){
- super(name);
- Log.d(TAG,"ctorE");
- //Addstates,useindentationtoshowhierarchy
- addState(mP1);
- addState(mS1,mP1);
- addState(mS2,mP1);
- addState(mP2);
- //Settheinitialstate
- setInitialState(mS1);
- Log.d(TAG,"ctorX");
- }
- classP1extendsState{
- @Overridepublicvoidenter(){
- Log.d(TAG,"mP1.enter");
- }
- @OverridepublicbooleanprocessMessage(Messagemessage){
- booleanretVal;
- Log.d(TAG,"mP1.processMessagewhat="+message.what);
- switch(message.what){
- caseCMD_2:
- //CMD_2willarriveinmS2beforeCMD_3
- sendMessage(obtainMessage(CMD_3));
- deferMessage(message);
- transitionTo(mS2);
- retVal=HANDLED;
- break;
- default:
- //Anymessagewedon'tunderstandinthisstateinvokesunhandledMessage
- retVal=NOT_HANDLED;
- break;
- }
- returnretVal;
- }
- @Overridepublicvoidexit(){
- Log.d(TAG,"mP1.exit");
- }
- }
- classS1extendsState{
- @Overridepublicvoidenter(){
- Log.d(TAG,"mS1.enter");
- }
- @OverridepublicbooleanprocessMessage(Messagemessage){
- Log.d(TAG,"S1.processMessagewhat="+message.what);
- if(message.what==CMD_1){
- //Transitiontoourselftoshowthatenter/exitiscalled
- transitionTo(mS1);
- returnHANDLED;
- }else{
- //Letparentprocessallothermessages
- returnNOT_HANDLED;
- }
- }
- @Overridepublicvoidexit(){
- Log.d(TAG,"mS1.exit");
- }
- }
- classS2extendsState{
- @Overridepublicvoidenter(){
- Log.d(TAG,"mS2.enter");
- }
- @OverridepublicbooleanprocessMessage(Messagemessage){
- booleanretVal;
- Log.d(TAG,"mS2.processMessagewhat="+message.what);
- switch(message.what){
- case(CMD_2):
- sendMessage(obtainMessage(CMD_4));
- retVal=HANDLED;
- break;
- case(CMD_3):
- deferMessage(message);
- transitionTo(mP2);
- retVal=HANDLED;
- break;
- default:
- retVal=NOT_HANDLED;
- break;
- }
- returnretVal;
- }
- @Overridepublicvoidexit(){
- Log.d(TAG,"mS2.exit");
- }
- }
- classP2extendsState{
- @Overridepublicvoidenter(){
- Log.d(TAG,"mP2.enter");
- sendMessage(obtainMessage(CMD_5));
- }
- @OverridepublicbooleanprocessMessage(Messagemessage){
- Log.d(TAG,"P2.processMessagewhat="+message.what);
- switch(message.what){
- case(CMD_3):
- break;
- case(CMD_4):
- break;
- case(CMD_5):
- transitionToHaltingState();
- break;
- }
- returnHANDLED;
- }
- @Overridepublicvoidexit(){
- Log.d(TAG,"mP2.exit");
- }
- }
- @Override
- voidonHalting(){
- Log.d(TAG,"halting");
- synchronized(this){
- this.notifyAll();
- }
- }
- P1mP1=newP1();
- S1mS1=newS1();
- S2mS2=newS2();
- P2mP2=newP2();
- }
- </code>
- *<p>IfthisisexecutedbysendingtwomessagesCMD_1andCMD_2
- *(Notethesynchronizeisonlyneededbecauseweusehsm.wait())</p>
- <code>
- Hsm1hsm=makeHsm1();
- synchronize(hsm){
- hsm.sendMessage(obtainMessage(hsm.CMD_1));
- hsm.sendMessage(obtainMessage(hsm.CMD_2));
- try{
- //waitforthemessagestobehandled
- hsm.wait();
- }catch(InterruptedExceptione){
- Log.e(TAG,"exceptionwhilewaiting"+e.getMessage());
- }
- }
- 输出如下:
- D/hsm1(1999):makeHsm1E
- D/hsm1(1999):ctorE
- D/hsm1(1999):ctorX
- D/hsm1(1999):mP1.enter
- D/hsm1(1999):mS1.enter
- D/hsm1(1999):makeHsm1X
- D/hsm1(1999):mS1.processMessagewhat=1
- D/hsm1(1999):mS1.exit
- D/hsm1(1999):mS1.enter
- D/hsm1(1999):mS1.processMessagewhat=2
- D/hsm1(1999):mP1.processMessagewhat=2
- D/hsm1(1999):mS1.exit
- D/hsm1(1999):mS2.enter
- D/hsm1(1999):mS2.processMessagewhat=2
- D/hsm1(1999):mS2.processMessagewhat=3
- D/hsm1(1999):mS2.exit
- D/hsm1(1999):mP1.exit
- D/hsm1(1999):mP2.enter
- D/hsm1(1999):mP2.processMessagewhat=3
- D/hsm1(1999):mP2.processMessagewhat=4
- D/hsm1(1999):mP2.processMessagewhat=5
- D/hsm1(1999):mP2.exit
- D/hsm1(1999):halting
Android状态机源码分析
分类:【Android 系统分析】 2013-08-30 19:13 470人阅读 评论(0) 收藏 举报 Android StateMachine 状态机 Handler state目录(?)[+]
在Android系统中,经常使用状态机来处理不同状态下的行为动作。状态机是将对象的状态与行为封装在一起;可以解决庞大的分支语句带来程序阅读性差和不便于进行扩展问题,使整个结构变得更加清晰明了,降低程序管理的复杂性提高灵活度。Android系统的StateMachine机制是一个State模式的应用,StateMachine是一个分层处理消息的状态机,并且是能够有分层排列状态。
构造状态机
StateMachine的构造函数都是protected类型,不能实例化,都是由其子类进行初始化操作。StateMachine有两个重载的构造函数,一个是通过指定消息循环对象来构造状态机
[java] view plain copy- protectedStateMachine(Stringname,Looperlooper){
- initStateMachine(name,looper);
- }
另一个则是直接启动一个消息循环线程来构造一个状态机
- protectedStateMachine(Stringname){
- //启动一个消息循环线程
- mSmThread=newHandlerThread(name);
- mSmThread.start();
- Looperlooper=mSmThread.getLooper();
- initStateMachine(name,looper);
- }
- privatevoidinitStateMachine(Stringname,Looperlooper){
- mName=name;
- mSmHandler=newSmHandler(looper,this);
- }
状态机中的每个状态使用State来封装,对于每个状态的信息又采用StateInfo来描述
StateMachine三个内部类:
1.ProcessedMessageInfo:保存已处理消息的信息;
2.ProcessedMessages:存储StateMachine最近处理的一些消息,需要保存最近处理的消息条数默认20,可以用户自己设定最大数目;
3.SmHandle是消息处理派发和状态控制切换的核心,运行在单独的线程上;
SmHandle成员变量定义:
ProcessedMessages用于保存已处理过的消息,mStateStack和mTempStateStack是一个数组栈,用于保存状态机中的链式状态关系。
mStateInfo定义为一个Hash链表,用于保存添加的所有状态。mInitialState保存初始状态,mDestState保存切换的目的状态。
建立树形层次结构状态机
在构造完一个状态机前需要向状态机中添加各种状态,StateMachine提供了addState函数来添加状态[java] view plain copy
- protectedfinalvoidaddState(Statestate,Stateparent){
- mSmHandler.addState(state,parent);
- }
- privatefinalStateInfoaddState(Statestate,Stateparent){
- if(mDbg){
- Log.d(TAG,"addStateInternal:Estate="+state.getName()
- +",parent="+((parent==null)?"":parent.getName()));
- }
- StateInfoparentStateInfo=null;
- if(parent!=null){
- parentStateInfo=mStateInfo.get(parent);
- if(parentStateInfo==null){
- //Recursivelyaddourparentasit'snotbeenaddedyet.
- parentStateInfo=addState(parent,null);
- }
- }
- StateInfostateInfo=mStateInfo.get(state);
- if(stateInfo==null){
- stateInfo=newStateInfo();
- mStateInfo.put(state,stateInfo);
- }
- //Validatethatwearen'taddingthesamestateintwodifferenthierarchies.
- if((stateInfo.parentStateInfo!=null)&&
- (stateInfo.parentStateInfo!=parentStateInfo)){
- thrownewRuntimeException("statealreadyadded");
- }
- stateInfo.state=state;
- stateInfo.parentStateInfo=parentStateInfo;
- stateInfo.active=false;
- if(mDbg)Log.d(TAG,"addStateInternal:XstateInfo:"+stateInfo);
- returnstateInfo;
- }
- 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);//设置初始状态
[java] view plain copy
- privatefinalStateInfoaddState(S0,null)
- {
- StateInfoparentStateInfo=null;
- //状态S0还未加入状态机中
- StateInfostateInfo=mStateInfo.get(state);
- if(stateInfo==null){
- //创建State详细信息对象
- stateInfo=newStateInfo();
- //将S0加入状态机中
- mStateInfo.put(state,stateInfo);
- }
- //设置状态S0的状态信息
- stateInfo.state=state;
- //S0的父节点为null
- stateInfo.parentStateInfo=parentStateInfo;
- stateInfo.active=false;
- returnstateInfo;
- }
[java] view plain copy
- privatefinalStateInfoaddState(Statestate,Stateparent)
- {
- StateInfoparentStateInfo=null;
- //状态S0在前面已经加入状态机中了
- if(parent!=null){
- //获取S0详细信息StateInfo
- parentStateInfo=mStateInfo.get(parent);
- //因为S0已经存在于状态机中,因此这里不为空
- if(parentStateInfo==null){
- //当前状态父状态未加入到StateMachine中,递归先加入其父State
- parentStateInfo=addState(parent,null);
- }
- }
- //从状态机中得到S1的状态信息,由于S1还为加入状态机,因此得到的结果为空
- StateInfostateInfo=mStateInfo.get(state);
- if(stateInfo==null){
- //创建State详细信息对象
- stateInfo=newStateInfo();
- //将S1加入状态机中
- mStateInfo.put(state,stateInfo);
- }
- //S1的状态信息刚创建,还没有为其设置父节点,因此其父节点为空
- if((stateInfo.parentStateInfo!=null)&&
- (stateInfo.parentStateInfo!=parentStateInfo)){
- thrownewRuntimeException("statealreadyadded");
- }
- //设置状态S1的状态信息
- stateInfo.state=state;
- //S1的父节点为S0
- stateInfo.parentStateInfo=parentStateInfo;
- stateInfo.active=false;
- returnstateInfo;
- }
启动状态机
当向状态机中添加完所有状态时,通过函数start函数来启动状态机 [java] view plain copy- publicvoidstart(){
- //mSmHandlercanbenullifthestatemachinehasquit.
- if(mSmHandler==null)return;
- /**Sendthecompleteconstructionmessage*/
- mSmHandler.completeConstruction();
- }
- privatefinalvoidcompleteConstruction(){
- if(mDbg)Log.d(TAG,"completeConstruction:E");
- //查找状态树的深度
- intmaxDepth=0;
- for(StateInfosi:mStateInfo.values()){
- intdepth=0;
- //根据父子关系计算树枝层次数
- for(StateInfoi=si;i!=null;depth++){
- i=i.parentStateInfo;
- }
- if(maxDepth<depth){
- maxDepth=depth;
- }
- }
- if(mDbg)Log.d(TAG,"completeConstruction:maxDepth="+maxDepth);
- //创建mStateStack,mTempStateStack状态栈
- mStateStack=newStateInfo[maxDepth];
- mTempStateStack=newStateInfo[maxDepth];
- //设置状态堆栈
- setupInitialStateStack();
- /**SendingSM_INIT_CMDmessagetoinvokeentermethodsasynchronously*/
- sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD,mSmHandlerObj));
- if(mDbg)Log.d(TAG,"completeConstruction:X");
- }
- privatefinalvoidsetupInitialStateStack(){
- //在mStateInfo中取得初始状态mInitialState对应的StateInfo
- StateInfocurStateInfo=mStateInfo.get(mInitialState);
- //从初始状态mInitialState开始根据父子关系填充mTempStateStack堆栈
- for(mTempStateStackCount=0;curStateInfo!=null;mTempStateStackCount++){
- mTempStateStack[mTempStateStackCount]=curStateInfo;
- curStateInfo=curStateInfo.parentStateInfo;
- }
- //EmptytheStateStack
- mStateStackTopIndex=-1;
- //将mTempStateStack中的状态按反序方式移动到mStateStack栈中
- moveTempStateStackToStateStack();
- }
mTempStateStackCount = 3; mStateStackTopIndex = -1; 然后调用函数moveTempStateStackToStateStack将节点以反序方式保存到mStateStack中 [java] view plain copy
- privatefinalintmoveTempStateStackToStateStack(){
- //startingIndex=0
- intstartingIndex=mStateStackTopIndex+1;
- inti=mTempStateStackCount-1;
- intj=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;
- returnstartingIndex;
- }
初始化完状态栈后,SmHandler将向消息循环中发送一个SM_INIT_CMD消息 [java] view plain copy
- sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD,mSmHandlerObj))
- elseif(!mIsConstructionCompleted&&(mMsg.what==SM_INIT_CMD)&&(mMsg.obj==mSmHandlerObj)){
- mIsConstructionCompleted=true;
- invokeEnterMethods(0);
- }
- performTransitions();
- privatefinalvoidinvokeEnterMethods(intstateStackEnteringIndex){
- for(inti=stateStackEnteringIndex;i<=mStateStackTopIndex;i++){
- if(mDbg)Log.d(TAG,"invokeEnterMethods:"+mStateStack[i].state.getName());
- mStateStack[i].state.enter();
- mStateStack[i].active=true;
- }
- }
状态切换
SmHandler在处理每个消息时都会调用performTransitions来检查状态切换 [java] view plain copy
- privatesynchronizedvoidperformTransitions(){
- while(mDestState!=null){
- //当前状态切换了存在于mStateStack中的State需要改变
- //仍然按照链式父子关系来存储
- //先从当前状态S3找到最近的被激活的parent状态S0
- //未被激活的全部保存起来(S3,S1)返回S0
- StateInfocommonStateInfo=setupTempStateStackWithStatesToEnter(destState);
- //将mStateStack中不属于当前状态(S3),
- //关系链上的State(S5,S2)退出(执行exit方法)
- invokeExitMethods(commonStateInfo);
- //将S3关系链加入到栈中(S3,S1)
- intstateStackEnteringIndex=moveTempStateStackToStateStack();
- //将新加入到mStateStack中未被激活的State激活(S3,S1)
- invokeEnterMethods(stateStackEnteringIndex);
- //将延迟的消息移动到消息队列的前面,以便快速得到处理
- moveDeferredMessageAtFrontOfQueue();
- }
- }
以上图中,初始状态为S4,现在目标状态mDestState被设置为S7。前面介绍了保存在mStateStack数组中的节点为: mStateStack={S0,S1,S4} mStateStackTopIndex = 2 这是以初始状态节点为起点遍历节点树得到的节点链表。 现在要切换到S7状态节点,则以S7为起始节点,同样遍历状态节点树,查找未激活的所有节点,并保存到mTempStateStack数组中 mTempStateStack={S7,S2,S0}
mTempStateStackCount = 3
接着调用mStateStack中除S0节点外的其他所有节点的exit函数,并且将每个状态节点设置为未激活状态,因此S4,S1被设置为未激活状态;将切换后的状态节点链表mTempStateStack移动到mStateStack, mStateStack={S0,S2,S7}
mStateStackTopIndex = 2 并调用节点S2,S7的enter函数,同时设置为激活状态。 理解了整个状态切换过程后,就能更好地理解代码,首先根据目标状态建立状态节点链路表 [java] view plain copy
- privatefinalStateInfosetupTempStateStackWithStatesToEnter(StatedestState){
- mTempStateStackCount=0;
- StateInfocurStateInfo=mStateInfo.get(destState);
- do{
- mTempStateStack[mTempStateStackCount++]=curStateInfo;
- if(curStateInfo!=null){
- curStateInfo=curStateInfo.parentStateInfo;
- }
- }while((curStateInfo!=null)&&!curStateInfo.active);
- returncurStateInfo;
- }
- privatefinalvoidinvokeExitMethods(StateInfocommonStateInfo){
- while((mStateStackTopIndex>=0)&&
- (mStateStack[mStateStackTopIndex]!=commonStateInfo)){
- StatecurState=mStateStack[mStateStackTopIndex].state;
- if(mDbg)Log.d(TAG,"invokeExitMethods:"+curState.getName());
- curState.exit();
- mStateStack[mStateStackTopIndex].active=false;
- mStateStackTopIndex-=1;
- }
- }
- privatefinalintmoveTempStateStackToStateStack(){
- //startingIndex=0
- intstartingIndex=mStateStackTopIndex+1;
- inti=mTempStateStackCount-1;
- intj=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;
- returnstartingIndex;
- }
- privatefinalvoidinvokeEnterMethods(intstateStackEnteringIndex){
- for(inti=stateStackEnteringIndex;i<=mStateStackTopIndex;i++){
- if(mDbg)Log.d(TAG,"invokeEnterMethods:"+mStateStack[i].state.getName());
- mStateStack[i].state.enter();
- mStateStack[i].active=true;
- }
- }
- protectedfinalvoidtransitionTo(IStatedestState){
- mSmHandler.transitionTo(destState);
- }
- privatefinalvoidtransitionTo(IStatedestState){
- mDestState=(State)destState;
- if(mDbg)Log.d(TAG,"transitionTo:destState="+mDestState.getName());
- }
消息处理
StateMachine处理的核心就是SmHandler,就是一个Handler,运行在单独线程中。Handler是用来异步处理派发消息,这里使用Handler管理各个状态,派发消息处理到各个状态中去执行。StateMachine提供了多个消息发送接口,通过这些接口函数可以将消息发送到SmHandler中。 [java] view plain copy
- publicfinalvoidsendMessage(intwhat){
- //mSmHandlercanbenullifthestatemachinehasquit.
- if(mSmHandler==null)return;
- mSmHandler.sendMessage(obtainMessage(what));
- }
- publicfinalvoidhandleMessage(Messagemsg){
- /**Savethecurrentmessage*/
- mMsg=msg;
- if(mIsConstructionCompleted){
- //派发当前消息到state中去处理
- processMsg(msg);
- }elseif(!mIsConstructionCompleted&&
- (mMsg.what==SM_INIT_CMD)&&(mMsg.obj==mSmHandlerObj)){
- /**Initialonetimepath.*/
- mIsConstructionCompleted=true;
- invokeEnterMethods(0);
- }else{
- thrownewRuntimeException("StateMachine.handleMessage:"+
- "Thestartmethodnotcalled,receivedmsg:"+msg);
- }
- //消息处理完毕更新mStateStack
- performTransitions();
- }
- privatefinalvoidprocessMsg(Messagemsg){
- StateInfocurStateInfo=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){
- StateorgState=mStateStack[mStateStackTopIndex].state;
- mProcessedMessages.add(msg,mSm.getMessageInfo(msg),curStateInfo.state,orgState);
- }else{
- mProcessedMessages.add(msg,mSm.getMessageInfo(msg),null,null);
- }
- }
- }
更多 1
- 顶
- 0
- 踩
更多相关文章
- Android(安卓)深入解析用户界面(一)
- android实现推送实践
- 【Android】Android消息处理机制
- Android进入suspend状态(goToSleep)
- Android应用程序的生命周期
- Android中的多线程之handler
- Android之——史上最简单自定义开关按钮的实现
- Android(安卓)Power Management
- Android(安卓)Handler 异步消息处理机制 《第一行代码》