Android StateMachine记录

分析例子

对StateMachine中例子进行逐步分析

其状态切换逻辑图如下:

        mP1      mP2
       /   \
      mS2   mS1 <-InitState
几条重要的概念:
  • 1 State方法有enter()/exit() 分别在进入和离开当前状态执行。
  • 2 需要重写State中processMessage来完成自己的状态切换逻辑。
  • 3 状态机初始化的时候,在根节点到初始节点上的节点都会执行enter。且执行顺序是从根节点开始。
  • 4 在进行状态切换的时候,是从目标节点向上查找跟当前的节点的共同父节点。如图:
     mP1
     /  \
    s1   s2
   /  \
 s3   s4  <- startstate
  /
s5  <- destate
// 从目标节点 s5 向上查找,找到s1是和s4 时共同父节点。
// 则从s4开始向上执行exit()方法。再从s3开始到s5 执行enter()方法。
  • 4 使用deferMessage会影响消息处理的顺序
class Hsm1 extends StateMachine {
    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("makeHsm1 E");
        Hsm1 sm = new Hsm1("hsm1");
        sm.start();
        log("makeHsm1 X");
        return sm;
    }

    Hsm1(String name) {
        super(name);
        log("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("ctor X");
    }

    class P1 extends State {
        @Override 
        public void enter() {
            log("mP1.enter");
        }
        @Override
        public boolean processMessage(Message message) {
            boolean retVal;
            log("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;
        }
        @Overrid
        public void exit() {
            log("mP1.exit");
        }
    }

    class S1 extends State {
       
       @Override 
        public void enter() {
            log("mS1.enter");
        }
       
       @Override 
       public boolean processMessage(Message message) {
            log("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("mS1.exit");
        }
    }

    class S2 extends State {
        @Override 
        public void enter() {
            log("mS2.enter");
        }
        
       @Override 
       public boolean processMessage(Message message) {
            boolean retVal;
            log("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("mS2.exit");
        }
    }

    class P2 extends State {
        @Override 
        public void enter() {
            log("mP2.enter");
            sendMessage(obtainMessage(CMD_5));
        }
        @Override 
        public boolean processMessage(Message message) {
            log("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("mP2.exit");
        }
    }

    @Override
    void onHalting() {
        log("halting");
        synchronized (this) {
            this.notifyAll();
        }
    }

    P1 mP1 = new P1();
    S1 mS1 = new S1();
    S2 mS2 = new S2();
    P2 mP2 = new P2();
}

分析源码

想要使用状态机分三步,

初始化流程

1 继承StateMachine。2 添加状态。3 启动状态机。

class Hsm1 extends StateMachine {
    public static Hsm1 makeHsm1() {
        log("makeHsm1 E");
        Hsm1 sm = new Hsm1("hsm1");
        sm.start();
        log("makeHsm1 X");
        return sm;
    }

    Hsm1(String name) {
        super(name);
        log("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("ctor X");
    }
   ...
}
  • 1 添加状态
    public final void addState(State state) {
        mSmHandler.addState(state, null);
    }

        private final StateInfo addState(State state, State parent) {
            ...
            StateInfo parentStateInfo = null;
            if (parent != null) {
                parentStateInfo = mStateInfo.get(parent);
                if (parentStateInfo == null) {
                    // Recursively add our parent as it's not been added yet.
                    parentStateInfo = addState(parent, null);
                }
            }
            StateInfo stateInfo = mStateInfo.get(state);
            if (stateInfo == null) {
                stateInfo = new StateInfo();
                mStateInfo.put(state, stateInfo);
            }
            ...
            stateInfo.state = state;
            stateInfo.parentStateInfo = parentStateInfo;
            stateInfo.active = false;
            if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
            return stateInfo;
        }

添加节点的时候,需要同时传入父节点。当没有父节点的时候,不执行递推查询。生成StateInfo和State进行映射。其实StateInfo就是一个链表。parentStateInfo是指向父节点的,active表明当前的节点是否被激活。

结合调用段的代码进行分析,

        //没有传入父节点,则mP1就是根节点,并将其加入mStateInfo Map中并进行映射
        //其StateInfo中的parentStateInfo为null,当前的节点并灭有被激活。
        addState(mP1);

        //传入mP1作为父节点,则从mStateInfo中取出的mP1的StateInfo
        //mStateInfo没有mS1的StateInfo信息,初始其StateInfo将其加入mStateInfo
        //其StateInfo中的parentStateInfo指向mP1,当前节点没有被激活
        addState(mS1, mP1);
        
        //同mS1 添加的分析步骤  
        addState(mS2, mP1);
        
        //同mP1 添加的分析步骤
        addState(mP2);
        
        //设置初始化的节点指向mS1,其后的代码就是简单的赋值
        setInitialState(mS1);

再所有的State添加完毕后,就需要启动状态机

    public static Hsm1 makeHsm1() {
        log("makeHsm1 E");
        Hsm1 sm = new Hsm1("hsm1");
        sm.start();
        log("makeHsm1 X");
        return sm;
    }

        //StateMachine.java
        private final void completeConstruction() {
            if (mDbg) mSm.log("completeConstruction: E");

            /**
             * Determine the maximum depth of the state hierarchy
             * so we can allocate the state stacks.
             */
             
             //查找最深的那个分支。换句话理解就是测量这颗树一共有多少度。
             //然后会根据maxDepth 创建数组。做成类似于栈结构
            int maxDepth = 0;
            for (StateInfo si : mStateInfo.values()) {
                int depth = 0;
                for (StateInfo i = si; i != null; depth++) {
                    i = i.parentStateInfo;
                }
                if (maxDepth < depth) {
                    maxDepth = depth;
                }
            }
            if (mDbg) mSm.log("completeConstruction: maxDepth=" + maxDepth);

            //根据maxDepth创建数组,是保证能装下从根节点到子节点中所有的路径
            mStateStack = new StateInfo[maxDepth];
            mTempStateStack = new StateInfo[maxDepth];
            
            //初始化State,做两步。1 从初始节点向上找到根节点。并将其放置在mTempStateStack
            //2 将mTempStateStack倒序拷贝到mStateStack
            setupInitialStateStack();

            /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
            sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));

            if (mDbg) mSm.log("completeConstruction: X");
        }
        
        //--- from completeConstruction()
        private final void setupInitialStateStack() {
            if (mDbg) {
                mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
            }
            
            //拿到初始节点,(StateInfo是一个指向根节点的单向链表, curStateInfo就像是一个指针)
            StateInfo curStateInfo = mStateInfo.get(mInitialState);
           
           //当前的链表指向初始节点,然后向上一直到根节点。  
           //(mS1->mP1)因为根节点的parenStateInfo是null。
           // mS1 curStateInfo != null mTempStateStackCount = 0;
           // mP1 curStateInfo.parentStateInfo != null mTempStateStackCount = 1;
           // null mP1.parentStateInfo == null mTempStateStackCount = 2;
            for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
                mTempStateStack[mTempStateStackCount] = curStateInfo;
                curStateInfo = curStateInfo.parentStateInfo;
            }

            // Empty the StateStack
            //记住此处将mStateStackTopIndex赋值为-1,因为后续的改变State也会用到此state
            mStateStackTopIndex = -1;
            
            //当前的mTempStateStack的顺序是 [mS1, mP1] 我们希望拿到顺序是[mP1, mS1]
            moveTempStateStackToStateStack();
        }

        //---  from setupInitialStateStack()
        private final int moveTempStateStackToStateStack() {
            // startingIndex为0
            int startingIndex = mStateStackTopIndex + 1;
            // mTempStateStackCount = 2, i = 1;
            int i = mTempStateStackCount - 1;
            // j = 0;
            int j = startingIndex;
            while (i >= 0) {  // i=1  ===>  i=0  ===>  i=-1(terminal)
                if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
                mStateStack[j] = mTempStateStack[i];
                j += 1;
                i -= 1;
            }
            
            // j = 2, mStateStackTopIndex = 1;
            mStateStackTopIndex = j - 1;
            if (mDbg) {
                mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
                        + ",startingIndex=" + startingIndex + ",Top="
                        + mStateStack[mStateStackTopIndex].state.getName());
            }
            
            //起始还是为0
            //为什么要返回这个了?是为了后面的在改变状态的是,从共同节点作为起点。
            return startingIndex;
        }


        //--- from sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
        // mSmHandlerObj是为了区分是状态机内部的消息,不是由外部进行驱动的。
        // 且状态机的启动只能由内部启动
        @Override
        public final void handleMessage(Message msg) {
            if (!mHasQuit) {
                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
                    mSm.onPreHandleMessage(msg);
                }

                if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);

                /** Save the current message */
                mMsg = msg;

                /** State that processed the message */
                State msgProcessedState = null;
                if (mIsConstructionCompleted || (mMsg.what == SM_QUIT_CMD)) {
                    /** Normal path */
                    msgProcessedState = processMsg(msg);
                } else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
                        && (mMsg.obj == mSmHandlerObj)) {
                    /** Initial one time path. */
                    mIsConstructionCompleted = true;
                    invokeEnterMethods(0);
                } else {
                    throw new RuntimeException("StateMachine.handleMessage: "
                            + "The start method not called, received msg: " + msg);
                }
                performTransitions(msgProcessedState, msg);

                // We need to check if mSm == null here as we could be quitting.
                if (mDbg && mSm != null) mSm.log("handleMessage: X");

                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
                    mSm.onPostHandleMessage(msg);
                }
            }
        }

        //--- from  handleMessage()
       private final void invokeEnterMethods(int stateStackEnteringIndex) {
            //此处mStateStackTopIndex = 1. 是在moveTempStateStackToStateStack方法中算出来的。
            //stateStackEnteringIndex = 0; 此处就是从根节点向下进行初始化  [mP1, mS1]
            //在调用state的enter()方法, 并将mStateInfo.active 置为 true
            for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
                if (stateStackEnteringIndex == mStateStackTopIndex) {
                    // Last enter state for transition
                    mTransitionInProgress = false;
                }
                if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
                mStateStack[i].state.enter();
                mStateStack[i].active = true;
            }
            
            mTransitionInProgress = false; // ensure flag set to false if no methods called
        }


     //--- from  handleMessage()
     //此方法是主要的处理方法
         private void performTransitions(State msgProcessedState, Message msg) {
            /**
             * If transitionTo has been called, exit and then enter
             * the appropriate states. We loop on this to allow
             * enter and exit methods to use transitionTo.
             */
             //orgState就是初始化节点
            State orgState = mStateStack[mStateStackTopIndex].state;
            ...
             // 当前mDestState为null, 此mDestState为状态迁移的
            State destState = mDestState;
            if (destState != null) {
                /**
                 * Process the transitions including transitions in the enter/exit methods
                 */
                while (true) {
                    if (mDbg) mSm.log("handleMessage: new destination call exit/enter");

                    /**
                     * Determine the states to exit and enter and return the
                     * common ancestor state of the enter/exit states. Then
                     * invoke the exit methods then the enter methods.
                     */
                    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
                    // flag is cleared in invokeEnterMethods before entering the target state
                    mTransitionInProgress = true;
                    invokeExitMethods(commonStateInfo);
                    int stateStackEnteringIndex = moveTempStateStackToStateStack();
                    invokeEnterMethods(stateStackEnteringIndex);

                    /**
                     * Since we have transitioned to a new state we need to have
                     * any deferred messages moved to the front of the message queue
                     * so they will be processed before any other messages in the
                     * message queue.
                     */
                    moveDeferredMessageAtFrontOfQueue();

                    if (destState != mDestState) {
                        // A new mDestState so continue looping
                        destState = mDestState;
                    } else {
                        // No change in mDestState so we're done
                        break;
                    }
                }
                mDestState = null;
            }

            /**
             * After processing all transitions check and
             * see if the last transition was to quit or halt.
             */
            if (destState != null) {
                if (destState == mQuittingState) {
                    /**
                     * Call onQuitting to let subclasses cleanup.
                     */
                    mSm.onQuitting();
                    cleanupAfterQuitting();
                } else if (destState == mHaltingState) {
                    /**
                     * Call onHalting() if we've transitioned to the halting
                     * state. All subsequent messages will be processed in
                     * in the halting state which invokes haltedProcessMessage(msg);
                     */
                    mSm.onHalting();
                }
            }
        }

执行输出的Log:

D/hsm1    ( 1999): makeHsm1 E
D/hsm1    ( 1999): ctor E
D/hsm1    ( 1999): ctor X
D/hsm1    ( 1999): mP1.enter
D/hsm1    ( 1999): mS1.enter
D/hsm1    ( 1999): makeHsm1 X
测试

分析完初始化流程,执行测试案例。

Hsm1 hsm = makeHsm1();
synchronize(hsm) {
//1
     hsm.sendMessage(obtainMessage(hsm.CMD_1));
//2     
     hsm.sendMessage(obtainMessage(hsm.CMD_2));
     try {
          // wait for the messages to be handled
          hsm.wait();
     } catch (InterruptedException e) {
          loge("exception while waiting " + e.getMessage());
     }
}
  • 1 外部触发
    测试代码是通过sendMessage从外面进行触发,在状态机中是由mSmHandler进行处理。并将message加入到MessageQueue的消息队列中,会在handleMessage()中进行处理。
 @Override
        public final void handleMessage(Message msg) {
            if (!mHasQuit) {
                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
                    //onPreHandleMessage是个空方法。子类可以自己实现
                    mSm.onPreHandleMessage(msg);
                }

               //在初始化完成后mIsConstructionCompleted = true;
               if (mIsConstructionCompleted || (mMsg.what == SM_QUIT_CMD)) {
                    /** Normal path */
                    msgProcessedState = processMsg(msg);
                }
                ...

                //再执行完S1.processMessage后,当前的mDestState为mS1
                performTransitions(msgProcessedState, msg);

                // We need to check if mSm == null here as we could be quitting.
                if (mDbg && mSm != null) mSm.log("handleMessage: X");

                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
                    mSm.onPostHandleMessage(msg);
                }
            }
        }


        //--- from handleMessage
        private final State processMsg(Message msg) {
            //从初始状态开始
            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
            if (mDbg) {
                mSm.log("processMsg: " + curStateInfo.state.getName());
            }

            if (isQuit(msg)) {
                transitionTo(mQuittingState);
            } else {
                //从初始节点调用processMessage方法。
                //如果当前节点可以处理跳过,如果当前节点不可处理。则调用父节点的processMessage方法
                //如果一直迭代到根节点还是无法处理此msg。则调用unhandleMessage.表示无法处理此msg
                while (!curStateInfo.state.processMessage(msg)) {
                    /**
                     * Not processed
                     */
                    curStateInfo = curStateInfo.parentStateInfo;
                    if (curStateInfo == null) {
                        /**
                         * No parents left so it's not handled
                         */
                        mSm.unhandledMessage(msg);
                        break;
                    }
                    if (mDbg) {
                        mSm.log("processMsg: " + curStateInfo.state.getName());
                    }
                }
            }
            return (curStateInfo != null) ? curStateInfo.state : null;
        }

上面的代码会执行到初始节点的processMessage方法,而初始节点的是mS1。我接着分析一下S1的代码。

    class S1 extends State {
        @Override
        public void enter() {
            log("mS1.enter");
        }
        
        @Override 
        public boolean processMessage(Message message) {
            log("S1.processMessage what=" + message.what);
            if (message.what == CMD_1) {
                //设置状态机的mDestState 为mS1
                transitionTo(mS1);
                // 返回true
                return HANDLED;
            } else {
                // Let parent process all other messages
                return NOT_HANDLED;
            }
        }
        @Override 
        public void exit() {
            log("mS1.exit");
        }
    }

     //StateMachine.java
        private final void transitionTo(IState destState) {
            if (mTransitionInProgress) {
                Log.wtf(mSm.mName, "transitionTo called while transition already in progress to " +
                        mDestState + ", new target state=" + destState);
            }
            mDestState = (State) destState;
            if (mDbg) mSm.log("transitionTo: destState=" + mDestState.getName());
        }

S1中的方法中只是将状态机的mDestState设置为mS1, 接下来我们在回到hanldMessage方法中。顺着逻辑执行performTransitions()

        private void performTransitions(State msgProcessedState, Message msg) {
            /**
             * If transitionTo has been called, exit and then enter
             * the appropriate states. We loop on this to allow
             * enter and exit methods to use transitionTo.
             */
             //此处为mS1
            State orgState = mStateStack[mStateStackTopIndex].state;
            ...
            //destState 为 mS1
            State destState = mDestState;
            if (destState != null) {
                /**
                 * Process the transitions including transitions in the enter/exit methods
                 */
                while (true) {
                    if (mDbg) mSm.log("handleMessage: new destination call exit/enter");

                    /**
                     * Determine the states to exit and enter and return the
                     * common ancestor state of the enter/exit states. Then
                     * invoke the exit methods then the enter methods.
                     */
                     //从目标节点向查找跟当前节点共同的父节点。
                    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
                    // flag is cleared in invokeEnterMethods before entering the target state
                    mTransitionInProgress = true;
                    //从当前节点一直共同的父节点(不包含共同的父节点),执行exit()方法
                    invokeExitMethods(commonStateInfo);
                    int stateStackEnteringIndex = moveTempStateStackToStateStack();
                    // 从共同的父节点一直到目标节点(不包含共同的父节点),执行enter方法
                    invokeEnterMethods(stateStackEnteringIndex);

                    /**
                     * Since we have transitioned to a new state we need to have
                     * any deferred messages moved to the front of the message queue
                     * so they will be processed before any other messages in the
                     * message queue.
                     */
                     //会将mDefer队列中的消息加到MessageQueue的头部。并清空
                    moveDeferredMessageAtFrontOfQueue();

                    if (destState != mDestState) {
                        // A new mDestState so continue looping
                        destState = mDestState;
                    } else {
                        // No change in mDestState so we're done
                        break;
                    }
                }
                mDestState = null;
            }

            /**
             * After processing all transitions check and
             * see if the last transition was to quit or halt.
             */
            if (destState != null) {
                if (destState == mQuittingState) {
                    /**
                     * Call onQuitting to let subclasses cleanup.
                     */
                    mSm.onQuitting();
                    cleanupAfterQuitting();
                } else if (destState == mHaltingState) {
                    /**
                     * Call onHalting() if we've transitioned to the halting
                     * state. All subsequent messages will be processed in
                     * in the halting state which invokes haltedProcessMessage(msg);
                     */
                    mSm.onHalting();
                }
            }
        }

//--- from performTransitions
//                            p1  
//                           / \
//       ^                 s0   s1
//       |                /  \    \
//       ^               s3   s4   s5 
//       |              /      \
//        destState -> s6       s7 <- currentState
// 如果当前节点是s7 则[P1, s0, s4, s7]为激活的节点(ative = true),
// 现在目标节点是s6,从s6往上一直查到s0为激活节点。
        private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
            /**
             * Search up the parent list of the destination state for an active
             * state. Use a do while() loop as the destState must always be entered
             * even if it is active. This can happen if we are exiting/entering
             * the current state.
             */
            mTempStateStackCount = 0;
            StateInfo curStateInfo = mStateInfo.get(destState);
            do {
                mTempStateStack[mTempStateStackCount++] = curStateInfo;
                curStateInfo = curStateInfo.parentStateInfo;
            } while ((curStateInfo != null) && !curStateInfo.active);

            if (mDbg) {
                mSm.log("setupTempStateStackWithStatesToEnter: X mTempStateStackCount="
                        + mTempStateStackCount + ",curStateInfo: " + curStateInfo);
            }
            return curStateInfo;
        }

//--- from performTransitions
//                            p1  
//                           / \
//    commonStateInfo  -> s0   s1
//                       /  \    \
//                     s3   s4   s5 
//                     /      \                   ^
//      destState -> s6       s7 <- currentState  |
//  从s7开始一直到s0为止,一路上的节点需要执行exit()方法,
//  同时mStateStackTopIndex会向上移动,直到指向s0.
        /**
         * Call the exit method for each state from the top of stack
         * up to the common ancestor state.
         */
        private final void invokeExitMethods(StateInfo commonStateInfo) {
            while ((mStateStackTopIndex >= 0)
                    && (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
                State curState = mStateStack[mStateStackTopIndex].state;
                if (mDbg) mSm.log("invokeExitMethods: " + curState.getName());
                curState.exit();
                mStateStack[mStateStackTopIndex].active = false;
                mStateStackTopIndex -= 1;
            }
        }

//--- from performTransitions
//    mStateEnterTopIndex   p1  
//                      \  / \
//    commonStateInfo  -> s0   s1
//                       /  \    \
//                     s3   s4   s5 
//                     /      \     
//      destState -> s6        s7 
// 从mStateEnterTopIndex向下一直到s6执行enter()方法。
        /**
         * Invoke the enter method starting at the entering index to top of state stack
         */
        private final void invokeEnterMethods(int stateStackEnteringIndex) {
            for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
                if (stateStackEnteringIndex == mStateStackTopIndex) {
                    // Last enter state for transition
                    mTransitionInProgress = false;
                }
                if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
                mStateStack[i].state.enter();
                mStateStack[i].active = true;
            }
            mTransitionInProgress = false; // ensure flag set to false if no methods called
        }
Hsm1 hsm = makeHsm1();
synchronize(hsm) {
//1  这个执行完毕,状态机的mDestState = mS1;
     hsm.sendMessage(obtainMessage(hsm.CMD_1));
//2  目前执行到这个位置。
     hsm.sendMessage(obtainMessage(hsm.CMD_2));
     try {
          // wait for the messages to be handled
          hsm.wait();
     } catch (InterruptedException e) {
          loge("exception while waiting " + e.getMessage());
     }
}

//根据前面的分析,会走到StateMachine的handleMessage,先执行S1.processMessage发现无法处理
//交付给P1.processMessage进行处理。所以接下来分析P1的代码。

    class P1 extends State {
       @Override public void enter() {
            log("mP1.enter");
        }
        @Override 
        public boolean processMessage(Message message) {
            boolean retVal;
            log("mP1.processMessage what=" + message.what);
            switch(message.what) {
            case CMD_2:
                // CMD_2 will arrive in mS2 before CMD_3
                //将CMD_3加到消息队列中
                sendMessage(obtainMessage(CMD_3));
                //将message(msg=CMD_2)加到defer队列中
                deferMessage(message);
                //将mDestState设置为mS2。
                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("mP1.exit");
        }
    }

//--- from handleMessage
//将调用deferMessage的消息加到MessageQueue队列之前。
        private final void moveDeferredMessageAtFrontOfQueue() {
            /**
             * The oldest messages on the deferred list must be at
             * the front of the queue so start at the back, which
             * as the most resent message and end with the oldest
             * messages at the front of the queue.
             */
            for (int i = mDeferredMessages.size() - 1; i >= 0; i--) {
                Message curMsg = mDeferredMessages.get(i);
                if (mDbg) mSm.log("moveDeferredMessageAtFrontOfQueue; what=" + curMsg.what);
                sendMessageAtFrontOfQueue(curMsg);
            }
            mDeferredMessages.clear();
        }

以上执行是 hsm.sendMessage(obtainMessage(hsm.CMD_1)); 的流程,执行往后输出的log的如下:

D/hsm1    ( 1999): mS1.processMessage what=1
D/hsm1    ( 1999): mS1.exit
D/hsm1    ( 1999): mS1.enter

后面的代码 hsm.sendMessage(obtainMessage(hsm.CMD_2)); 也是走相同的流程,只不过需要结合不同的State中processMessage代码进行分析。

总结

综上整体的状态机流程如下:

  • 1 设置不同State之间的父子关系。
  • 2 设定初始State
  • 3 启动状态机
  • 4 重写State processMessage 定义状态切换的逻辑
  • 5 transitationTo() 来切换下一个目标状态
  • 6 可以通过deferMessage()来改变消息的处理优先级。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值