Android StateMachine总结(二)创建流程

本文详细介绍了Android中StateMachine的创建过程,包括通过静态方法获取实例、建立状态树、设置初始状态以及启动状态机的步骤。文章分析了状态机的内部实现,如线程和Looper的使用,以及如何通过addState()构建状态树。启动状态机时,重点讲解了初始化状态栈和调用enter方法的流程。强调状态机在启动前必须设定初始状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录


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

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

2、建立状态树

3、设初始状态

4、Start状态机

###流程图
这里写图片描述
上图是创建状态机的流程图,一个深绿色的大框框代表一步,与上相对应。

##代码分析
对应的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.youkuaiyun.com/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;
           }
  }

上面两点用图这样表示:
这里写图片描述

如此过程便完成了状态机的start。
注意:状态机在start前一定要设置初始状态,不然,everything is spadework.

##END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值