Android中的设计模式(3)

状态的转换会导致当前状态的退出,和新状态的进入,当从当前状态退出时,会逐层向上调用父状态的退出exit函数,但注意,这种逐层调用,会在当前状态和目标状态的共同父状态处不再执行exit(),如果前状态和目标状态的不存在共同的父状态,则彻底退出当前状态的所有父状态,并进入新状态。

private final void invokeExitMethods(StateInfo commonStateInfo) {//commonStateInfo是前状态和目标状态的共同父状态 while ((mStateStackTopIndex >= 0) && (mStateStack[mStateStackTopIndex] != commonStateInfo)) { State curState = mStateStack[mStateStackTopIndex].state; if (mDbg) Log.d(TAG, "invokeExitMethods: " + curState.getName()); curState.exit(); mStateStack[mStateStackTopIndex].active = false; mStateStackTopIndex -= 1; } }

状态机还可以调用deferMessage方法和sendMessageAtFrontOfQueue方法。
deferMessage方法会将该消息保存在一个延迟队列中,这时并不发送出去,而是会在下一次状态转变的时候(例如从A状态变为B状态),将延迟队列中的所有消息放在消息队列的最前面。这些消息就会在B状态作为当前状态时被处理。
sendMessageAtFrontOfQueue方法会调用状态机的Handler的sendMessageAtFrontOfQueue()方法,将当前发送的消息,排在消息队列的最前面而不是原本的最后面。
为了说明这些特性,下面是一个具有8个状态的状态层次。

mP0 / \ mP1 mS0 / \ mS2 mS1 / \ \ mS3 mS4 mS5 ---> 初始状态

当状态机开始后,进入初始状态mS5,各个父状态同样也是活动的,于是mP0, mP1, mS1 和mS5都是活动的。当有一个消息发出来,就会依次调用mS5,
mS1, mP1, mP0的processMessage方法(前提是都会返回false或者NOT_HANDLED)。
然后现在假设mS5的processMessage可以处理这个消息,并且会调用transitionTo(mS4)将状态转为mS4,然后返回true 或 HANDLED。processMessage返回后会进入performTransitions方法,其会找到mS5和mS4的共同父状态,也就是mP1。紧接着会依次调用mS5.exit, mS1.exit 然后是 mS2.enter mS4.enter. 这时mP0, mP1, mS2,mS4 这四个状态是活动的,当下一个消息到来的时候,就会激活mS4.processMessage方法。

下面是一个继承了StateMachine的HelloWorld。该状态机会在接收每一个消息的时候,打印一个 “Hello World” 字符串。

class HelloWorld extends StateMachine { HelloWorld(String name) { super(name); addState(mState1); setInitialState(mState1); } public static HelloWorld makeHelloWorld() { HelloWorld hw = new HelloWorld("hw"); hw.start(); return hw; } class State1 extends State { @Override public boolean processMessage(Message message) { Log.d(TAG, "Hello World"); return HANDLED; } } State1 mState1 = new State1(); }

1

void testHelloWorld() { HelloWorld hw = makeHelloWorld(); hw.sendMessage(hw.obtainMessage()); }

1

下面是一个具有4个状态的状态机,并分为2个独立的父状态 mP1 mP2 / \ mS2 mS1--初始状态

下面是这几个状态的伪代码

state mP1 { enter { log("mP1.enter"); } exit { log("mP1.exit"); } on msg { CMD_2 { send(CMD_3); defer(msg); transitonTo(mS2); return HANDLED; } return NOT_HANDLED; } } state mS1 parent mP1 { enter { log("mS1.enter"); } exit { log("mS1.exit"); } on msg { CMD_1 { transitionTo(mS1); return HANDLED; } return NOT_HANDLED; } } state mS2 parent mP1 { enter { log("mS2.enter"); } exit { log("mS2.exit"); } on msg { CMD_2 { send(CMD_4); return HANDLED; } CMD_3 { defer(msg); transitionTo(mP2); return HANDLED; } return NOT_HANDLED; } } state mP2 { enter { log("mP2.enter"); send(CMD_5); } exit { log("mP2.exit"); } on msg { CMD_3, CMD_4 { return HANDLED; } CMD_5 { transitionTo(HaltingState); return HANDLED; } return NOT_HANDLED; } } 测试代码: class Hsm1 extends StateMachine { private static final String TAG = "hsm1"; 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.d(TAG, "makeHsm1 E"); Hsm1 sm = new Hsm1("hsm1"); sm.start(); Log.d(TAG, "makeHsm1 X"); return sm; } Hsm1(String name) { super(name); Log.d(TAG, "ctor E"); // 添加状态 addState(mP1); addState(mS1, mP1); addState(mS2, mP1); addState(mP2); // 设定初始状态 setInitialState(mS1); Log.d(TAG, "ctor X"); } class P1 extends State { @Override public void enter() { Log.d(TAG, "mP1.enter"); } @Override public boolean processMessage(Message message) { boolean retVal; Log.d(TAG, "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; } @Override public void exit() { Log.d(TAG, "mP1.exit"); } } class S1 extends State { @Override public void enter() { Log.d(TAG, "mS1.enter"); } @Override public boolean processMessage(Message message) { Log.d(TAG, "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.d(TAG, "mS1.exit"); } } class S2 extends State { @Override public void enter() { Log.d(TAG, "mS2.enter"); } @Override public boolean processMessage(Message message) { boolean retVal; Log.d(TAG, "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.d(TAG, "mS2.exit"); } } class P2 extends State { @Override public void enter() { Log.d(TAG, "mP2.enter"); sendMessage(obtainMessage(CMD_5)); } @Override public boolean processMessage(Message message) { Log.d(TAG, "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.d(TAG, "mP2.exit"); } } @Override void onHalting() { Log.d(TAG, "halting"); synchronized (this) { this.notifyAll(); } } P1 mP1 = new P1(); S1 mS1 = new S1(); S2 mS2 = new S2(); P2 mP2 = new P2(); } //注意:添加synchronize块是因为我们使用了hsm.wait()。 Hsm1 hsm = makeHsm1();//创建StateMachine对象 synchronize(hsm) { hsm.sendMessage(obtainMessage(hsm.CMD_1)); hsm.sendMessage(obtainMessage(hsm.CMD_2)); try { // wait for the messages to be handled hsm.wait(); } catch (InterruptedException e) { Log.e(TAG, "exception while waiting " + e.getMessage()); } } 输出: 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 D/hsm1 ( 1999): mS1.processMessage what=1 D/hsm1 ( 1999): mS1.exit D/hsm1 ( 1999): mS1.enter D/hsm1 ( 1999): mS1.processMessage what=2 D/hsm1 ( 1999): mP1.processMessage what=2 D/hsm1 ( 1999): mS1.exit D/hsm1 ( 1999): mS2.enter D/hsm1 ( 1999): mS2.processMessage what=2 D/hsm1 ( 1999): mS2.processMessage what=3 D/hsm1 ( 1999): mS2.exit D/hsm1 ( 1999): mP1.exit D/hsm1 ( 1999): mP2.enter D/hsm1 ( 1999): mP2.processMessage what=3 D/hsm1 ( 1999): mP2.processMessage what=4 D/hsm1 ( 1999): mP2.processMessage what=5 D/hsm1 ( 1999): mP2.exit D/hsm1 ( 1999): halting

1

画一个流程图 状态机的实例–DataConnection

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/21cf657be5adb10b5c3e5a3111333ab9.html