代码改变世界

Android stateMachine分析

2013-07-28 21:42  ...平..淡...  阅读(1275)  评论(0编辑  收藏  举报

StateMachine与State模式的详细介绍可以参考文章:Android学习 StateMachine与State模式

 

下面是我对于StateMachine的理解:

先了解下消息处理。看下StateMachine::sendMessage方法。

不管BT/Wifi中,都有继承StateMachine的子类(BluetoothAdapterStateMachine.java/WifiStateMachine.java),在某些类中,会创建这些类的对象,当需要发送消息时,会调用它们的sendMessage方法,即调用父类StateMachine的sendMessage方法。

    /**
     * Enqueue a message to this state machine.
     */
    public final void sendMessage(int what) {
        // mSmHandler can be null if the state machine has quit.
        if (mSmHandler == null) return;

        mSmHandler.sendMessage(obtainMessage(what));
    }

    /**
     * Enqueue a message to this state machine.
     */
    public final void sendMessage(int what, Object obj) {
        // mSmHandler can be null if the state machine has quit.
        if (mSmHandler == null) return;

        mSmHandler.sendMessage(obtainMessage(what,obj));
    }

    /**
     * Enqueue a message to this state machine.
     */
    public final void sendMessage(Message msg) {
        // mSmHandler can be null if the state machine has quit.
        if (mSmHandler == null) return;

        mSmHandler.sendMessage(msg);
    }

从sendMessage方法中可以看到,实际上是调用了StateMachine::SmHandler::sendMessage方法,该类没有实现该方法,所以会调用父类Handler::sendMessage方法,然后会调用StateMachine::SmHandler::handleMessage方法进行处理:

        /**
         * Handle messages sent to the state machine by calling
         * the current state's processMessage. It also handles
         * the enter/exit calls and placing any deferred messages
         * back onto the queue when transitioning to a new state.
         */
        @Override
        public final void handleMessage(Message msg) {
            if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what);

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

            if (mIsConstructionCompleted) {
                /** Normal path */
                processMsg(msg); //1
            } 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(); //2

            if (mDbg) Log.d(TAG, "handleMessage: X");
        }

 该方法中有两个重要的方法:

1.processMsg(msg);

        /**
         * Process the message. If the current state doesn't handle
         * it, call the states parent and so on. If it is never handled then
         * call the state machines unhandledMessage method.
         */
        private final void processMsg(Message msg) {
            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
            if (mDbg) {
                Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
            }
            while (!curStateInfo.state.processMessage(msg)) {
                /**
                 * Not processed
                 */
                curStateInfo = curStateInfo.parentStateInfo;
                if (curStateInfo == null) {
                    /**
                     * No parents left so it's not handled
                     */
                    mSm.unhandledMessage(msg);
                    if (isQuit(msg)) {
                        transitionTo(mQuittingState);
                    }
                    break;
                }
                if (mDbg) {
                    Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
                }
            }

            /**
             * Record that we processed the message
             */
            if (mSm.recordProcessedMessage(msg)) {
                if (curStateInfo != null) {
                    State orgState = mStateStack[mStateStackTopIndex].state;
                    mProcessedMessages.add(msg, mSm.getMessageInfo(msg), curStateInfo.state,
                            orgState);
                } else {
                    mProcessedMessages.add(msg, mSm.getMessageInfo(msg), null, null);
                }
            }
        }

 

这个方法中有一个while循环,看下条件:curStateInfo.state.processMessage(msg),即调用当前状态(State具体的子类)的processMessage方法。在具体实现的State子类中,在processMessage方法中,在具体的case处理完message后,会返回true 或 false(true的话会使得上述代码中的while循环退出,即该消息不上传给父状态处理,自己处理完就好了;false的话,就是再上传给父状态处理)。

 

2.performTransitions();

        /**
         * Do any transitions
         */
        private void performTransitions() {
            /**
             * 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.
             */
            State destState = null;
            while (mDestState != null) {
                if (mDbg) Log.d(TAG, "handleMessage: new destination call exit");

                /**
                 * Save mDestState locally and set to null
                 * to know if enter/exit use transitionTo.
                 */
                destState = mDestState;
                mDestState = null;

                /**
                 * 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);
                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();
            }

            /**
             * After processing all transitions check and
             * see if the last transition was to quit or halt.
             */
            if (destState != null) {
                if (destState == mQuittingState) {
                    cleanupAfterQuitting();

                } else if (destState == mHaltingState) {
                    /**
                     * Call halting() if we've transitioned to the halting
                     * state. All subsequent messages will be processed in
                     * in the halting state which invokes haltedProcessMessage(msg);
                     */
                    mSm.halting();
                }
            }
        }

 

 这个方法主要是完成:

1.当前状态的切换,

2.更新状态栈。

比如状态已经通过addState方法添加完毕,形成了树形结构。当前状态是S4,现在要切换到S5。performTransitions方法中会完成一项功能:pop S4 S1,push S2 S5。