Android StateMachine实践

 我们在实际应用中经常遇到状态设计模式,Android 框架中给我们提供了一个经典的状态模式实现——StateMachine。在StateMachine之前,先来看下状态设计模式定义和UML类图。
 状态模式:当一个对象的内在状态改变时,允许改变其行为。状态模式中行为是由状态来决定的,不同的状态下有不同的行为。状态模式的意图是让一个对象在其内部状态改变时,其行为也随之改变。

 状态模式的UML类图:


Context:环境类,定义客户感兴趣的接口,维护一个State子类的实例,这个实例定义了对象的当前状态。
State:抽象状态类或者状态接口,定义一个或者一组接口,表示该状态下的行为。
ConcreteStateA、ConcreteStateB:具体状态类,每一个具体的状态类实现抽象State中定义的接口,从而达到不同状态下的不同行为。

 接下来我们将分析Android中的StateMachine实现。首先看下StateMachine的UML类图,从图中可以看到,StateMachine的UML类图符合状态模式的设计原则,IState接口代表一组接口,表示该状态下的行为。HaltingState和QuittingState代表具体的状态,StateMachine对象维护当前状态,提供客户端感兴趣的接口。


 IState接口定义在frameworks/core/java/com/android/internal/util/IState.java中
 State接口定义frameworks/core/java/com/android/internal/util/State.java类中
 StateMachine类定义在frameworks/core/java/com/android/internal/util/StateMachine.java中。


  IState接口
   IState接口定义了一组方法,表示该状态下的行为。

  • enter()
            当进入一个状态时调用该方法;
  • exit()
           当退出一个状态时调用该方法;
  • processMessage()
           当状态机处理消息时调用该方法;
  • getName()
          返回状态的名字,调试使用;

 

State类
    State类提供一个IState接口的基本实现。State类必须实现processMessage方法,可选地实现enter和exit函数,这两个方法等价于构造函数和析构函数,用于初始化和清理相关的工作。


StateMachine类
    StateMachine是一个层次式状态机,可以管理和处理状态的跳转。StateMachine是基于Handler来实现的,通过Message来驱动状态的跳转。首先来看下状态机的构建:

    /**
     * 状态机的构建函数
     *
     * @param name 状态机的名字
     */
    protected StateMachine(String name) {
        //通过HandlerThread来处理消息
        mSmThread = new HandlerThread(name);
        mSmThread.start();
        Looper looper = mSmThread.getLooper();

        initStateMachine(name, looper);
    }

    /**
     * 初始化状态机
     *
     * @param looper 状态机使用的Looper
     * @param name 状态机名字
     */
    private void initStateMachine(String name, Looper looper) {
        mName = name;
        mSmHandler = new SmHandler(looper, this);
    }

    /*
    * SmHandler继承自Handler
    */
    private SmHandler(Looper looper, StateMachine sm) {
            super(looper);
            mSm = sm;//持有一个状态机的引用

            //将Halting和Quitting状态添加到状态列表中
            addState(mHaltingState, null);
            addState(mQuittingState, null);
    }
 当一个状态机被创建,通过addState函数来构建状态的层级,通过setInitialState函数来设置初始状态。

        /**
         * 添加一个新的状态到状态机
         * 
         *
         * @param 需要添加的状态
         * @param parent the 状态的父状态
         * @return stateInfo 返回当前状态的信息
         */
        private final StateInfo addState(State state, State parent) {

            StateInfo parentStateInfo = null;
            if (parent != null) {
                parentStateInfo = mStateInfo.get(parent);
                if (parentStateInfo == null) {
                    //如果parent状态还未添加,则先添加parent状态
                    parentStateInfo = addState(parent, null);
                }
            }
            StateInfo stateInfo = mStateInfo.get(state);
            if (stateInfo == null) {
                stateInfo = new StateInfo();
                //将状态添加到状态集合中
                mStateInfo.put(state, stateInfo);
            }

            //验证是否存在相同的状态,不同parent的情况,保证一个状态只有一个parent状态存在
            if ((stateInfo.parentStateInfo != null)
                    && (stateInfo.parentStateInfo != parentStateInfo)) {
                throw new RuntimeException("state already added");
            }
            stateInfo.state = state;
            stateInfo.parentStateInfo = parentStateInfo;
            stateInfo.active = false;
            return stateInfo;
        }

        /*
        * 状态信息
        */
        private class StateInfo {
            /** 状态 */
            State state;

            /** 父类状态信息,如果没有父类状态,则为空 */
            StateInfo parentStateInfo;

            /** True when the state has been entered and on the stack */
            boolean active;

            /**
             * Convert StateInfo to string
             */
            @Override
            public String toString() {
                return "state=" + state.getName() + ",active=" + active + ",parent="
                        + ((parentStateInfo == null) ? "null" : pa
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值