StateMachine 使用及源码解读,kotlin 面试题
private HaltingState mHaltingState = new HaltingState();// Quiting 状态 private QuittingState mQuittingState = new QuittingState();
// map,存储 State 和 StateInfo 的对应表 private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();// 初始状态 private State mInitialState;// 目标状态 private State mDestState;
private SmHandler(Looper looper, StateMachine sm) {super(looper);mSm = sm;// 默认将 HaltingState 和 QuittingState 加入状态机 addState(mHaltingState, null);addState(mQuittingState, null);}}
QuittingState
/**
State entered when a valid quit message is handled.*/private class QuittingState extends State {@Overridepublic boolean processMessage(Message msg) {// 所有消息都不作处理 return NOT_HANDLED;}}
HaltingState
/**
State entered when transitionToHaltingState is called.*/private class HaltingState extends State {@Overridepublic boolean processMessage(Message msg) {// 和 quitting 的不同在于,可以处理消息,所有的消息都调用 haltedProcessMessagemSm.haltedProcessMessage(msg);return true;}}
StateMachine#start
public void start() {// mSmHandler 有可能为空,如果调用了 quit,会被置空。如果调用了 quit,statemachine 的很多资源会被释放,调用 start 无法再次开启 if (mSmHandler == null) return;// 初始化一些参数 mSmHandler.completeConstruction();}
private final void completeConstruction() {// 获取整个状态表的深度 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;}}// 根据深度来初始化 StateStack 和 TempStateStackmStateStack = new StateInfo[maxDepth];mTempStateStack = new StateInfo[maxDepth];setupInitialStateStack();// 发送 SM_INIT_CMD message,异步调用 enter 方法 sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));}
SmHandler#setupInitialStateStack
// 收到 SM_INIT_CMD 消息后,转移到初始状态 private final void setupInitialStateStack() {StateInfo curStateInfo = mStateInfo.get(mInitialState);// 将初始状态及其所有父状态加入 tempStackfor (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {mTempStateStack[mTempStateStackCount] = curStateInfo;curStateInfo = curStateInfo.parentStateInfo;}// 清空 StateStackmStateStackTopIndex = -1;// 将 tempStateStack 移动到 StateStackmoveTempStateStackToStateStack();}
SmHandler#addState
private final StateInfo addState(State state, State parent) {StateInfo parentStateInfo = null;if (parent != null) {parentStateInfo = mStateInfo.get(parent);if (parentStateInfo == null) {// 如果 parent 未添加,手动添加 parentStateInfo = addState(parent, null);}}StateInfo stateInfo = mStateInfo.get(state);if (stateInfo == null) {// 创建 StateInfo,添加到 map 中 stateInfo = new StateInfo();mStateInfo.put(state, stateInfo);}// 重复指定不一样的 parent,抛异常 if ((stateInfo.parentStateInfo != null) &&(stateInfo.parentStateInfo != parentStateInfo)) {throw new RuntimeException("state already added");}// stateInfo 保存了当前状态、父状态、是否 activestateInfo.state = state;stateInfo.parentStateInfo = parentStateInfo;// 调用 enter 后,active 为 true,exit 后,active 为 falsestateInfo.active = false;return stateInfo;}
SmHandler#handleMessage
@Overridepublic final void handleMessage(Message msg) {mMsg = msg;if (mIsConstructionCompleted) {// 已经初始化完之后的常规路径 processMsg(msg);} else if (!mIsConstructionCompleted &&(mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {// 未初始化完的路径,调用 enter
mIsConstructionCompleted = true;invokeEnterMethods(0);} else {throw new RuntimeException("StateMachine.handleMessage: " +"The start method not called, received msg: " + msg);}// 执行 transitionsperformTransitions();}
SmHandler#processMsg
private final void processMsg(Message msg) {StateInfo curStateInfo = mStateStack[mStateStackTopIndex];if (isQuit(msg)) {// 如果是退出 msg,转移到退出状态 transitionTo(mQuittingState);} else {// 循环遍历父状态,看是否能处理 while (!curStateInfo.state.processMessage(msg)) {curStateInfo = curStateInfo.parentStateInfo;if (curStateInfo == null) {// 如果没有状态可以处理,调用此处 mSm.unhandledMessage(msg);break;}}}}
SmHandler#transitionTo
private final void transitionTo(IState destState) {// 只改变 mDestState,具体的执行在 performTransitions 中 mDestState = (State) destState;}
SmHandler#performTransitions
private void performTransitions() {State destState = null;while (mDestState != null) {destState = mDestState;mDestState = null;// 找到目标状态非 active 的父状态,将链路中父状态放入 tempStack 中。返回目标状态与当前状态的公共祖先 StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);// 将 stateStack 中,公共祖先之前的状态出栈并调用 exitinvokeExitMethods(commonStateInfo);// 将 tempStack 中的状态入栈到 StateStackint stateStackEnteringIndex = moveTempStateStackToStateStack();// 调用新入栈的 state 的 enter 回调 invokeEnterMethods(stateStackEnteringIndex);// 将 defer message 移动到消息队列最前面// defer message 的意思是,将消息保存在列表中,状态转移后将消息放置到队列最前面,优先被处理 moveDeferredMessageAtFrontOfQueue();}// 处理 quiting 和 Haling 状态
评论