Android 源码的状态模式

Android 源码的状态模式

状态模式介绍

状态模式中的行为是由状态来决定的,不同的状态下有不同的行为。状态模式和策略模式的结构几乎完全一样,但它们的目的、本质却完全不一样。状态模式的行为是平行的、不可替换的,策略模式的行为是彼此独立、可相互替换的。用一句话来表述,状态模式把对象的行为包装在不同的状态对象里,每一个状态对象都有一个共同的抽象状态基类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。

状态模式的定义

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

StateMachine

Android 的 Wifi 状态切换会使用 WifiController 类。

/**
 * WifiController is the class used to manage on/off state of WifiStateMachine for various operating
 * modes (normal, airplane, wifi hotspot, etc.).
 */
public class WifiController extends StateMachine {

WifiController 类继承了 StateMachine 类。StateMachine 是一个状态机,它的实现是一种状态模式。

StateMachine 的 sendMessage 方法如下:

    public void sendMessage(int what) {
        // mSmHandler can be null if the state machine has quit.
        SmHandler smh = mSmHandler;
        if (smh == null) return;

        smh.sendMessage(obtainMessage(what));
    }

sendMessage 方法通过 SmHandler 发送消息。

SmHandler

SmHandler 的代码如下:

    private static class SmHandler extends Handler {
    ...
        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;
    ...
        }
    ...

StateInfo 是 SmHandler 的内部类,用来保存状态信息。state 是当前状态,parentStateInfo 是上一个状态,active 表示状态是否激活。

SmHandler 的 handleMessage 代码如下:

        @Override
        public final void handleMessage(Message msg) {
            if (!mHasQuit) {
                ...
                    msgProcessedState = processMsg(msg);
                ...
                performTransitions(msgProcessedState, msg);
                ...
            }
        }

handleMessage 首先通过 processMsg 处理消息,然后通过 performTransitions 执行状态转换。

processMsg 方法如下:

        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;
        }

如果当前状态处理了消息,就返回当前状态,否则循环寻找它的上一个状态来处理。如果没有状态处理,会调用 unhandledMessage 方法。

performTransitions 方法如下:

private void performTransitions(State msgProcessedState, Message msg) {
            ...
            State orgState = mStateStack[mStateStackTopIndex].state;
            ...
            State destState = mDestState;
            if (destState != null) {
                ...
                while (true) {
                    ...
                    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
                    // flag is cleared in invokeEnterMethods before entering the target state
                    mTransitionInProgress = true;
                    invokeExitMethods(commonStateInfo);
                    int stateStackEnteringIndex = moveTempStateStackToStateStack();
                    invokeEnterMethods(stateStackEnteringIndex);
                    ...
        }

orgState 是原始状态,destState 是目标状态。invokeExitMethods 先退出状态,然后用 invokeEnterMethods 进入新的状态。

addState

WifiController 在构造是初始化了一些状态。

    WifiController(Context context, WifiStateMachine wsm, Looper wifiStateMachineLooper,
                   WifiSettingsStore wss, Looper wifiServiceLooper, FrameworkFacade f,
                   WifiStateMachinePrime wsmp) {
        super(TAG, wifiServiceLooper);
        ...
        // CHECKSTYLE:OFF IndentationCheck
        addState(mDefaultState);
            addState(mStaDisabledState, mDefaultState);
            addState(mStaEnabledState, mDefaultState);
                addState(mDeviceActiveState, mStaEnabledState);
            addState(mStaDisabledWithScanState, mDefaultState);
            addState(mEcmState, mDefaultState);
        // CHECKSTYLE:ON IndentationCheck
        ...
    }

WifiController 使用 addState 添加状态。

这里的 6 个 addState 方法没有按照正常的空格缩进。为了表示层级关系,越底层的状态缩进的越多。

mDefaultState 是最顶层的 State,mStaDisabledState、mStaEnabledState、mStaDisabledWithScanState、mEcmState 是第二层的 State,mDeviceActiveState 是最底层的 State。

addState 方法如下:

        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.state = state;
            stateInfo.parentStateInfo = parentStateInfo;
            stateInfo.active = false;
            ...
            return stateInfo;
        }

addState 方法通过递归的方式构造了 stateInfo。

状态之间不是跨越式转换的,当前状态只能转换到上一个状态或者下一个状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值