zoukankan      html  css  js  c++  java
  • StateMachine

    简单使用阐述

    在应用开发中也可以使用源码中的StateMachine类,只要从源码中把StateMachineState类拷贝到我们的工程目录就可以使用。

    Android 中的状态机是一个分层的消息处理机制,每一层都会有一到多个节点,而状态机的消息就是在这些节点之间流转处理,如下结构所示:

    // 状态机分层结构
              mP0
             /   
            mP1   mS0
           /       
          mS2       mS1
         /          
        mS3  mS4     mS5  ---> initial state 初始节点
    

    而节点就是State类,它实现了IState接口,除了enterexit方法外,还有processMessage方法,表示用来处理节点的消息。若返回HANDLED则表示消息处理完成,若返回NOT_HANDLED则表示消息没有处理。

    构造状态机

    在我们使用 StateMachine 之前,要构造好所需的状态分层结构。通过addState方法来向状态机中添加节点,例如如下的状态结构,mS1 和 mS2 节点有公共的父节点 mP1,同时还有一个孤立的节点 mP2。

          // 状态分层结构设定
            mP1      mP2
           /   
          mS2   mS1
          // 构造状态机结构代码
          addState(mP1);
              addState(mS1, mP1);
              addState(mS2, mP1);
          addState(mP2);
    

    addState方法添加节点时,还能指定其父节点添加。

    当我们构造完了状态机时,还需要指定其中一个节点为启动点,消息从启动点开始处理,通过setInitialState方法来指定启动点,最后通过start方法启动状态机。

    状态机消息处理

    当构造完想要的状态机结构时,就是对状态机内部消息流转的处理了。

    start状态机时,状态机的第一个动作就是调用节点的enter方法,不过,它调用的是指定的启动点的最远的父节点的enter方法,然后再是次一级的父节点的enter方法,最后才是启动点的enter方法,就如同上面的结构所示,先调用 mP1 点,然后才是 mS1 点的方法,此时 mS1 节点就是状态机的当前对外的点。由此可见,当启动点进入 enter状态时,它的父节点,直至最顶层的父节点都进入了enter状态了。

    状态机中的每个节点都 0 个或 1 个父节点,当子节点不能处理当前消息时,它可以通过返回NOT_HANDLED将当前消息传递给其父节点来处理。如果一个消息从未被处理过,那么unhandledMessage方法将会被调用给最后一次机会来处理该消息。

    除此之外,节点还可以通过transitionTo方法将当前节点转移至另外一个新的节点。

              mP0
             /   
            mP1   mS0
           /       
          mS2      mS1
         /         
        mS3  mS4    mS5  ---> initial state
    

    例如,当 mS5 处理消息,想要将当前节点转移至 mS4 时,那么它会先找到 mS5 和 mS4 最近的公有父节点 mP1。然后,除了这个最近的公有父节点 mP1 以及它的上层节点外,mS5 进入enter状态时启动的那些父节点都会退出,调用exit方法。最后再由 mP1 节点下的节点调用enter方法直到新节点 mS4 调用了enter方法。

    也就是说,从 mS5 到 mS4 状态的转变,先是 mS5、mS1 调用了exit方法,再是 mS2、mS4 调用了enter方法,这就是状态机中节点发生状态转移时的调用过程。

    除此之外,节点还可以调用deferMessagesendMessageAtFroneOfQueue方法。deferMessage方法使得消息存储在消息队列中,当状态转移到新节点时才会处理,而sendMessageAtFrontOfQueue方法则是将消息放置到消息队列的头部。

    当状态机的所有消息都完成时,可以调用transitionToHaltingState方法来将状态机处理停止状态。此时,状态机将转移到HaltingState停止状态,并调用halting方法。随后收到的所有消息都只是会调用haltedProcessMessage方法来处理了。

    若想要完全的停止状态机,则可以使用quit或者quitNow方法来处理。

  • 相关阅读:
    bzoj2733 永无乡 平衡树按秩合并
    bzoj2752 高速公路 线段树
    bzoj1052 覆盖问题 二分答案 dfs
    bzoj1584 打扫卫生 dp
    bzoj1854 游戏 二分图
    bzoj3316 JC loves Mkk 二分答案 单调队列
    bzoj3643 Phi的反函数 数学 搜索
    有一种恐怖,叫大爆搜
    BZOJ3566 概率充电器 概率dp
    一些奇奇怪怪的过题思路
  • 原文地址:https://www.cnblogs.com/fynnn/p/15511843.html
Copyright © 2011-2022 走看看