天天看点

Android StateMachine总结(二)创建流程

文章目录

##综述

创建状态机的流程主要是这几步:

1、通过MyStateMachine的静态方法,得到实例

2、建立状态树

3、设初始状态

4、Start状态机

###流程图

Android StateMachine总结(二)创建流程

上图是创建状态机的流程图,一个深绿色的大框框代表一步,与上相对应。

##代码分析

对应的server端MyStateMachine代码大概是这样:

public class MyStateMachine extends StateMachine{

   public static MyStateMachine makeHsm1() {
       MyStateMachine sm = new MyStateMachine("hsm1");
       sm.start();
       return sm;
   }
   MyStateMachine(String name) {
       super(name);
       // Add states, use indentation to show hierarchy
       addState(mS1);
       addState(mS2, mS1);
       ... ...
       
       // Set the initial state
       setInitialState(mS4);
   }
   class S1 extends State {
       @Override
       public void enter() {
           super.enter();
       }
       @Override
       public boolean processMessage(Message message) {
            super.processMessage();
       }   
       @Override
       public void exit() {
           super.exit();
       }
   }
... ... 
           

client端由MyStateMachine stateMachine = MyStateMachine.makeHsm1()得到状态机唯一实例。

###通过MyStateMachine的静态方法,得到实例

StateMachine的构造方法:

protected StateMachine(String name) {

       mSmThread = new HandlerThread(name);
       mSmThread.start();
       Looper looper = mSmThread.getLooper();
       initStateMachine(name, looper);
}
           

这是initStateMachine:

private void initStateMachine(String name, Looper looper) {

   mName = name;
   mSmHandler = new SmHandler(looper, this);
}
           

从中看到,启一个mSmThread的线程,获取它的Looper对象,并和SmHandlr关联。得到SmHandler实例。

MyStateMachine的构造函数默认是protect,不能从其它非继承类创建实例,只能makeHsm1()静态方法获得唯一实例,该方法new MyStateMachine实例。 这便是单例模式,这里使用时为了避免有一大堆MyStateMachine实例,不然就乱套了。

###建立状态树

  • 通过addState()方法建立状态树。
  • 该步骤上一篇博客已说过,见https://blog.csdn.net/lijunxie/article/details/81302421。
  • addState()的原理是将当前状态和其父状态关联起来,加到一个HashMap中,这样通过子状态便能找到其父状态,(不能通过父状态找到子状态,我们的状态也用不上这样的功能,因为状态之间的跳转不涉及其子状态),可以多个状态拥有共同的父状态,这样便达到类似树的关系。

###设初始状态

private final void setInitialState(State initialState) {
       if (mDbg) mSm.log("setInitialState: initialState=" + initialState.getName());
           mInitialState = initialState;
       }
           

这一步只是将 InitialState 赋个mInitialState 变量,该变量有什么用,怎么用在下一步中详细介绍。

###Start状态机

如上流程图所示,StateMachine.java提供start()方法,它只是封装的SmHandler的completeConstruction()方法。

如上篇wiki所示,该方法里最重要的是这两步:

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));
           

第一,初始化mStateStack和mTempStateStack 这两个数组,maxDepth是树的深度, 并往里面填充数据。这数据是怎们填充的呢?

第二,发送SM_INIT_CMD消息,SmHandler的handleMessage接收到后,调invokeEnterMethods(0), 这个方法其实就是遍历mStateStack数组,并依次调state的enter方法,代码是这样的:

private final void invokeEnterMethods(int stateStackEnteringIndex) {
           for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
                  mStateStack[i].state.enter();
                 mStateStack[i].active = true;
           }
  }
           

上面两点用图这样表示:

Android StateMachine总结(二)创建流程

如此过程便完成了状态机的start。

注意:状态机在start前一定要设置初始状态,不然,everything is spadework.

##END