安卓StateMachine运行过程理解(翻译)

最近研究了一下WifiStateMachine,发现它主要继承了StateMachine,这里根据StateMachine文件的英文文档进行翻译。

1. 这个State Machine是一个层级状态机

    下面是我移动这个statemachine到安卓应用上面来进行调试的版本:

     点击下载:  测试代码

2.每一个状态都是state结构体的一个子类实现

每个子类都必须实现state的processMessage函数,其余的enter/exit/getName是可选实现的。


enter/exit这种实现方式和面向对象的构造函数和析构函数很像。知道它的原理就行了。


3.状态机的创建


通过addState可以把所以状态和这个状态的依赖关系添加到状态机里面去。最终就会形成一个相互依赖的树结构。

然后再通过setInitialState设置状态机的初始状态。以后的状态机就从这里开始。

最后调用start函数启动状态机,这个方法会调用和当前状态有关的所有enter方法,而且调用顺序从第一个父节点开始,这个其实和面向对象的构造方法的调用很像。

比如说有如下的三个状态,

         mP1
       /           \
    mS2      mS1 ----> initial state

那么这棵树需要这样来创建:

addState(mS2,mP1);

addState(mS1,mP1);

setInitialState(mS1);

start();

其中初始状态是mS1,调用start后

enter的调用顺序是mP1->enter();,mS1->enter();

4.状态机的转换

调用transitionTo函数用于状态机的转换。转换的过程中遵循如下的原则。

比较当前的状态的父状态是否和要切换的有一样的,如果有一样,假设他是mP1:就调用当前状态一直到mP1(不包括)的exit函数,然后再冲mP1到新状态的所有节点的enter.

比较当前的状态的父状态是否和要切换的有一样的,如果不一样,就调用当前状态的exit函数,以及其所有父状态的exit函数,然后再从新状态的第一个父状态的enter函数一直调用到当前状态enter。

5.消息处理

涉及到消息处理如果做过安卓应用的都知道有一个叫Handler的东西,这个东西会和一个线程结合起来工作。其实stateMachine的处理方法就用的这个机制。只不过进行了功能多的包装而已。

要给当前状态发送消息时只需要调用sendMessage就可以了,当然还要构造消息,这里用obtainMessage,其实这两个函数就是Handler的包装。

当消息发送后就会调用当前状态的processMessage函数,这里它有三种处理办法:

(1). 如果自己处理不了就返回false 或者 NOT_HANDLED.这样stateMachine就会去调用它的父亲的processMessage,直到处理成功或者最终都没有调用那么unhandledMessage()会被调用。

(2).如果所有的状态都完成了就会调用transitionToHaltingState,调用了它之后,所有的消息都由transitionToHaltingState来处理了。

(3).如果当前消息自己还是没法处理,需要切换到其他状态处理,那么它可以调用deferMessage这样可以把当前的消息保存直到状态切换后处理的第一个消息里面。

最后是谷歌的例子:

class Hsm1 extends StateMachine {
    private static final String TAG = "hsm1";
    public static final int CMD_1 = 1;
    public static final int CMD_2 = 2;
    public static final int CMD_3 = 3;
    public static final int CMD_4 = 4;
    public static final int CMD_5 = 5;
    public static Hsm1 makeHsm1() {
        Log.d(TAG, "makeHsm1 E");
        Hsm1 sm = new Hsm1("hsm1");
        sm.start();
        Log.d(TAG, "makeHsm1 X");
        return sm;
    }


    Hsm1(String name) {
        super(name);
        Log.d(TAG, "ctor E");


        // Add states, use indentation to show hierarchy
        addState(mP1);
            addState(mS1, mP1);
            addState(mS2, mP1);
        addState(mP2);


        // Set the initial state
        setInitialState(mS1);
        Log.d(TAG, "ctor X");
    }


    class P1 extends State {
        @Override public void enter() {
            Log.d(TAG, "mP1.enter");
        }
        @Override public boolean processMessage(Message message) {
            boolean retVal;
            Log.d(TAG, "mP1.processMessage what=" + message.what);
            switch(message.what) {
            case CMD_2:
                // CMD_2 will arrive in mS2 before CMD_3
                sendMessage(obtainMessage(CMD_3));
                deferMessage(message);
                transitionTo(mS2);
                retVal = HANDLED;
                break;
            default:
                // Any message we don't understand in this state invokes unhandledMessage
                retVal = NOT_HANDLED;
                break;
            }
            return retVal;
        }
        @Override public void exit() {
            Log.d(TAG, "mP1.exit");
        }
    }


    class S1 extends State {
        @Override public void enter() {
            Log.d(TAG, "mS1.enter");
        }
        @Override public boolean processMessage(Message message) {
            Log.d(TAG, "S1.processMessage what=" + message.what);
            if (message.what == CMD_1) {
                // Transition to ourself to show that enter/exit is called
                transitionTo(mS1);
                return HANDLED;
            } else {
                // Let parent process all other messages
                return NOT_HANDLED;
            }
        }
        @Override public void exit() {
            Log.d(TAG, "mS1.exit");
        }
    }


    class S2 extends State {
        @Override public void enter() {
            Log.d(TAG, "mS2.enter");
        }
        @Override public boolean processMessage(Message message) {
            boolean retVal;
            Log.d(TAG, "mS2.processMessage what=" + 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;
            }
            return retVal;
        }
        @Override public void exit() {
            Log.d(TAG, "mS2.exit");
        }
    }


    class P2 extends State {
        @Override public void enter() {
            Log.d(TAG, "mP2.enter");
            sendMessage(obtainMessage(CMD_5));
        }
        @Override public boolean processMessage(Message message) {
            Log.d(TAG, "P2.processMessage what=" + message.what);
            switch(message.what) {
            case(CMD_3):
                break;
            case(CMD_4):
                break;
            case(CMD_5):
                transitionToHaltingState();
                break;
            }
            return HANDLED;
        }
        @Override public void exit() {
            Log.d(TAG, "mP2.exit");
        }
    }


    @Override
    void halting() {
        Log.d(TAG, "halting");
        synchronized (this) {
            this.notifyAll();
        }
    }


    P1 mP1 = new P1();
    S1 mS1 = new S1();
    S2 mS2 = new S2();
    P2 mP2 = new P2();
}
它所构造的树结构:

          mP1                 mP2
        /           \
      mS2   mS1

如果用下面的代码开始状态机:

Hsm1 hsm = hsm.makeHsm1();
synchronize(hsm) {
     hsm.sendMessage(
hsm.
obtainMessage(hsm.CMD_1)); hsm.sendMessage(hsm.obtainMessage(hsm.CMD_2)); try { // wait for the messages to be handled hsm.wait(); } catch (InterruptedException e) { Log.e(TAG, "exception while waiting " + e.getMessage()); }}

最后输出:D/hsm1    ( 1999): makeHsm1 ED/hsm1    ( 1999): ctor ED/hsm1    ( 1999): ctor XD/hsm1    ( 1999): mP1.enterD/hsm1    ( 1999): mS1.enterD/hsm1    ( 1999): makeHsm1 XD/hsm1    ( 1999): mS1.processMessage what=1D/hsm1    ( 1999): mS1.exitD/hsm1    ( 1999):
 mS1.enterD/hsm1    ( 1999): mS1.processMessage what=2D/hsm1    ( 1999): mP1.processMessage what=2D/hsm1    ( 1999): mS1.exitD/hsm1    ( 1999): mS2.enterD/hsm1    ( 1999): mS2.processMessage what=2D/hsm1    ( 1999): mS2.processMessage what=3D/hsm1    ( 1999):
 mS2.exitD/hsm1    ( 1999): mP1.exitD/hsm1    ( 1999): mP2.enterD/hsm1    ( 1999): mP2.processMessage what=3D/hsm1    ( 1999): mP2.processMessage what=4D/hsm1    ( 1999): mP2.processMessage what=5D/hsm1    ( 1999): mP2.exitD/hsm1    ( 1999): halting


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值