美文网首页
Android之WIFI-基础篇StateMachine分析

Android之WIFI-基础篇StateMachine分析

作者: 锄禾豆 | 来源:发表于2022-02-11 20:11 被阅读0次

    概述

    StateMachine即状态机的关键在于内部类SmHandler
    

    原理

    StateMachine的核心是SmHandler.SmHanlder的核心为HashMap mStateInfo,因为mStateInfo促成了树状图
    

    源码

    7.1
    

    分析关键api

    1.构造方法
        protected StateMachine(String name, Looper looper) {
            initStateMachine(name, looper);//创建内部类对象SmHandler
        }
        
        private void initStateMachine(String name, Looper looper) {
            mName = name;
            mSmHandler = new SmHandler(looper, this);//SmHandler构造方法带了StateMachine本身对象
        }
        
            private SmHandler(Looper looper, StateMachine sm) {
                super(looper);
                mSm = sm;//SmHandler传入的StateMachine对象
    
                addState(mHaltingState, null);
                addState(mQuittingState, null);
            }
    
    2.addState
        protected final void addState(State state, State parent) {
            mSmHandler.addState(state, parent);
        }
        
            private final StateInfo addState(State state, State parent) {
                if (mDbg) {
                    mSm.log("addStateInternal: E state=" + state.getName() + ",parent="
                            + ((parent == null) ? "" : parent.getName()));
                }
                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);
                }
    
                // Validate that we aren't adding the same state in two different hierarchies.
                if ((stateInfo.parentStateInfo != null)
                        && (stateInfo.parentStateInfo != parentStateInfo)) {
                    throw new RuntimeException("state already added");
                }
                stateInfo.state = state;
                stateInfo.parentStateInfo = parentStateInfo;
                stateInfo.active = false;
                if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
                return stateInfo;
            }
            
            /** The map of all of the states in the state machine */
            private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();
            
            private class StateInfo {
                /** The state */
                State state;
    
                /** The parent of this state, null if there is no parent */
                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" : parentStateInfo.state.getName());
                }
            }
            
            父状态和子状态建立联系的实现
            1.建立一个HashMap对象,把State和StateInfo关联起来
            2.StateInfo带着State、StateInfo等变量,通过StateInfo把子父关系一一建立起来
    
    
    3.start
        public void start() {
            // mSmHandler can be null if the state machine has quit.
            SmHandler smh = mSmHandler;
            if (smh == null) return;
    
            /** Send the complete construction message */
            smh.completeConstruction();
        }
    
            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.
                 */
                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);
    
                mStateStack = new StateInfo[maxDepth];
                mTempStateStack = new StateInfo[maxDepth];
                setupInitialStateStack();//确认执行顺序
    
                /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
                sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));//树立执行步骤
    
                if (mDbg) mSm.log("completeConstruction: X");
            }
            
            代码片段1:setupInitialStateStack
            private final void setupInitialStateStack() {//建立临时栈mTempStateStack,0-->n (子状态-->父状态)
                if (mDbg) {
                    mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
                }
    
                StateInfo curStateInfo = mStateInfo.get(mInitialState);
                for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
                    mTempStateStack[mTempStateStackCount] = curStateInfo;
                    curStateInfo = curStateInfo.parentStateInfo;
                }
    
                // Empty the StateStack
                mStateStackTopIndex = -1;
    
                moveTempStateStackToStateStack();
            }
            
            private final int moveTempStateStackToStateStack() {//建立真实环境栈mStateStack,0-->n (父状态-->子状态)
                int startingIndex = mStateStackTopIndex + 1;
                int i = mTempStateStackCount - 1;
                int j = startingIndex;
                while (i >= 0) {
                    if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
                    mStateStack[j] = mTempStateStack[i];
                    j += 1;
                    i -= 1;
                }
    
                mStateStackTopIndex = j - 1;
                if (mDbg) {
                    mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
                            + ",startingIndex=" + startingIndex + ",Top="
                            + mStateStack[mStateStackTopIndex].state.getName());
                }
                return startingIndex;
            }
            
            代码片段2:sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj))
    
            public final void handleMessage(Message msg) {//核心功能的实现处
                if (!mHasQuit) {
                    if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
                        mSm.onPreHandleMessage(msg);//mSm为状态机对象,如果在消息分发前需要处理部分业务,可以继承重写onPreHandleMessage
                    }
    
                    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) {
                        /** 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);//处理状态切换的业务。即transitionTo(destState)
    
                    // 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);//mSm为状态机对象,如果在消息分发后需要处理部分业务,可以继承重写onPostHandleMessage
                    }
                }
            }
            
            片段2的细化片段1:invokeEnterMethods(0)
            private final void invokeEnterMethods(int stateStackEnteringIndex) {
                for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
                    if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
                    mStateStack[i].state.enter();//i逐渐增大,执行顺序:父状态-->当前子状态
                    mStateStack[i].active = true;
                }
            }
    
            片段2的细化片段2:processMsg(msg)
            private final State processMsg(Message msg) {
                StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
                if (mDbg) {
                    mSm.log("processMsg: " + curStateInfo.state.getName());
                }
    
                if (isQuit(msg)) {
                    transitionTo(mQuittingState);
                } else {
                    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;
            }
    
            片段2的细化片段3:performTransitions(msgProcessedState, msg)
            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.
                 */
                State orgState = mStateStack[mStateStackTopIndex].state;
    
                /**
                 * Record whether message needs to be logged before we transition and
                 * and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
                 * always set msg.obj to the handler.
                 */
                boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
    
                if (mLogRecords.logOnlyTransitions()) {
                    /** Record only if there is a transition */
                    if (mDestState != null) {
                        mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState,
                                orgState, mDestState);
                    }
                } else if (recordLogMsg) {
                    /** Record message */
                    mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState,
                            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);
                        invokeExitMethods(commonStateInfo);//exit,从子状态到父状态,依次执行
                        int stateStackEnteringIndex = moveTempStateStackToStateStack();
                        invokeEnterMethods(stateStackEnteringIndex);//enter,从父状态到子状态,依次执行
    
                        /**
                         * 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();
                    }
                }
            }
    

    总结

    1.状态机启动后,调用各种状态,先执行父状态enter,再执行子状态enter。相当于构造函数执行流程。
    2.状态切换,先执行老状态的exit业务(先子状态exit,再父状态exit),再执行新状态的enter业务(先父状态enter,在子状态enter).注意:共同的父状态为结点
    3.状态处理消息时,如果子状态处理不了,则交给父状态处理
    4.一条消息的处理流程为
    a.当前状态处理消息
    b.处理转化的消息
    b1)当前状态处理exit
    b2)新状态处理enter
    b3)处理在延迟池中的消息
    

    相关文章

      网友评论

          本文标题:Android之WIFI-基础篇StateMachine分析

          本文链接:https://www.haomeiwen.com/subject/wgwqkrtx.html