Android Data Analyse(4)--StateMachine
来源:互联网 发布:java.util. 编辑:程序博客网 时间:2024/05/27 09:45
StateMachine 定义
英文定义
/* * * <p>The state machine defined here is a hierarchical state machine which processes messages * and can have states arranged hierarchically.</p> * * <p>A state is a <code>State</code> object and must implement * <code>processMessage</code> and optionally <code>enter/exit/getName</code>. * The enter/exit methods are equivalent to the construction and destruction * in Object Oriented programming and are used to perform initialization and * cleanup of the state respectively. The <code>getName</code> method returns the * name of the state; the default implementation returns the class name. It may be * desirable to have <code>getName</code> return the the state instance name instead, * in particular if a particular state class has multiple instances.</p> * * <p>When a state machine is created, <code>addState</code> is used to build the * hierarchy and <code>setInitialState</code> is used to identify which of these * is the initial state. After construction the programmer calls <code>start</code> * which initializes and starts the state machine. The first action the StateMachine * is to the invoke <code>enter</code> for all of the initial state's hierarchy, * starting at its eldest parent. The calls to enter will be done in the context * of the StateMachine's Handler, not in the context of the call to start, and they * will be invoked before any messages are processed. For example, given the simple * state machine below, mP1.enter will be invoked and then mS1.enter. Finally, * messages sent to the state machine will be processed by the current state; * in our simple state machine below that would initially be mS1.processMessage.</p><pre> mP1 / \ mS2 mS1 ----> initial state</pre> * <p>After the state machine is created and started, messages are sent to a state * machine using <code>sendMessage</code> and the messages are created using * <code>obtainMessage</code>. When the state machine receives a message the * current state's <code>processMessage</code> is invoked. In the above example * mS1.processMessage will be invoked first. The state may use <code>transitionTo</code> * to change the current state to a new state.</p> * * <p>Each state in the state machine may have a zero or one parent states. If * a child state is unable to handle a message it may have the message processed * by its parent by returning false or NOT_HANDLED. If a message is not handled by * a child state or any of its ancestors, <code>unhandledMessage</code> will be invoked * to give one last chance for the state machine to process the message.</p> * * <p>When all processing is completed a state machine may choose to call * <code>transitionToHaltingState</code>. When the current <code>processingMessage</code> * returns the state machine will transfer to an internal <code>HaltingState</code> * and invoke <code>halting</code>. Any message subsequently received by the state * machine will cause <code>haltedProcessMessage</code> to be invoked.</p> * * <p>If it is desirable to completely stop the state machine call <code>quit</code> or * <code>quitNow</code>. These will call <code>exit</code> of the current state and its parents, * call <code>onQuitting</code> and then exit Thread/Loopers.</p> * * <p>In addition to <code>processMessage</code> each <code>State</code> has * an <code>enter</code> method and <code>exit</code> method which may be overridden.</p> * * <p>Since the states are arranged in a hierarchy transitioning to a new state * causes current states to be exited and new states to be entered. To determine * the list of states to be entered/exited the common parent closest to * the current state is found. We then exit from the current state and its * parent's up to but not including the common parent state and then enter all * of the new states below the common parent down to the destination state. * If there is no common parent all states are exited and then the new states * are entered.</p> * * <p>Two other methods that states can use are <code>deferMessage</code> and * <code>sendMessageAtFrontOfQueue</code>. The <code>sendMessageAtFrontOfQueue</code> sends * a message but places it on the front of the queue rather than the back. The * <code>deferMessage</code> causes the message to be saved on a list until a * transition is made to a new state. At which time all of the deferred messages * will be put on the front of the state machine queue with the oldest message * at the front. These will then be processed by the new current state before * any other messages that are on the queue or might be added later. Both of * these are protected and may only be invoked from within a state machine.</p> * * <p>To illustrate some of these properties we'll use state machine with an 8 * state hierarchy:</p><pre> mP0 / \ mP1 mS0 / \ mS2 mS1 / \ \ mS3 mS4 mS5 ---> initial state</pre> * <p>After starting mS5 the list of active states is mP0, mP1, mS1 and mS5. * So the order of calling processMessage when a message is received is mS5, * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this * message by returning false or NOT_HANDLED.</p> * * <p>Now assume mS5.processMessage receives a message it can handle, and during * the handling determines the machine should change states. It could call * transitionTo(mS4) and return true or HANDLED. Immediately after returning from * processMessage the state machine runtime will find the common parent, * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So * when the next message is received mS4.processMessage will be invoked.</p> * * <p>Now for some concrete examples, here is the canonical HelloWorld as a state machine. * It responds with "Hello World" being printed to the log for every message.</p><pre>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("Hello World"); return HANDLED; } } State1 mState1 = new State1();}void testHelloWorld() { HelloWorld hw = makeHelloWorld(); hw.sendMessage(hw.obtainMessage());}</pre> * <p>A more interesting state machine is one with four states * with two independent parent states.</p><pre> mP1 mP2 / \ mS2 mS1</pre> * <p>Here is a description of this state machine using pseudo code.</p> <pre>state mP1 { enter { log("mP1.enter"); } exit { log("mP1.exit"); } on msg { CMD_2 { send(CMD_3); defer(msg); transitionTo(mS2); return HANDLED; } return NOT_HANDLED; }}INITIALstate 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; }}</pre> * <p>The implementation is below and also in StateMachineTest:</p><pre>class Hsm1 extends StateMachine { 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("makeHsm1 E"); Hsm1 sm = new Hsm1("hsm1"); sm.start(); log("makeHsm1 X"); return sm; } Hsm1(String name) { super(name); log("ctor E"); // Add states, use indentation to show hierarchy addState(mP1); addState(mS1, mP1); addState(mS2, mP1); addState(mP2); // Set the initial state setInitialState(mS1); log("ctor X"); } class P1 extends State { @Override public void enter() { log("mP1.enter"); } @Override public boolean processMessage(Message message) { boolean retVal; log("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("mP1.exit"); } } class S1 extends State { @Override public void enter() { log("mS1.enter"); } @Override public boolean processMessage(Message message) { log("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("mS1.exit"); } } class S2 extends State { @Override public void enter() { log("mS2.enter"); } @Override public boolean processMessage(Message message) { boolean retVal; log("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("mS2.exit"); } } class P2 extends State { @Override public void enter() { log("mP2.enter"); sendMessage(obtainMessage(CMD_5)); } @Override public boolean processMessage(Message message) { log("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("mP2.exit"); } } @Override void onHalting() { log("halting"); synchronized (this) { this.notifyAll(); } } P1 mP1 = new P1(); S1 mS1 = new S1(); S2 mS2 = new S2(); P2 mP2 = new P2();}</pre> * <p>If this is executed by sending two messages CMD_1 and CMD_2 * (Note the synchronize is only needed because we use hsm.wait())</p><pre>Hsm1 hsm = makeHsm1();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) { loge("exception while waiting " + e.getMessage()); }}</pre> * <p>The output is:</p><pre>D/hsm1 ( 1999): makeHsm1 ED/hsm1 ( 1999): ctor ED/hsm1 ( 1999): ctor XD/hsm1 ( 1999): mP1.enterD/hsm1 ( 1999): mS1.enterD/hsm1 ( 1999): makeHsm1 XD/hsm1 ( 1999): mS1.processMessage what=1D/hsm1 ( 1999): mS1.exitD/hsm1 ( 1999): mS1.enterD/hsm1 ( 1999): mS1.processMessage what=2D/hsm1 ( 1999): mP1.processMessage what=2D/hsm1 ( 1999): mS1.exitD/hsm1 ( 1999): mS2.enterD/hsm1 ( 1999): mS2.processMessage what=2D/hsm1 ( 1999): mS2.processMessage what=3D/hsm1 ( 1999): mS2.exitD/hsm1 ( 1999): mP1.exitD/hsm1 ( 1999): mP2.enterD/hsm1 ( 1999): mP2.processMessage what=3D/hsm1 ( 1999): mP2.processMessage what=4D/hsm1 ( 1999): mP2.processMessage what=5D/hsm1 ( 1999): mP2.exitD/hsm1 ( 1999): halting</pre> */
中文翻译
StateMachine 能有层次的处理状态消息。
State 是某种状态的对象,它必须实现processMessage 的方法,可以选择性的实现enter()/exit()/getName()的方法。enter()/exit() 方法是为了创建和销毁State. getName ()这个方法返回该state的名字,默认返回的是state 的类名。这样可以避免一个特定的state有多个对象从而导致返回值不同。
当StateMachine被创建,将会调用addState()这个方法来创建state的层次(?),然后调用setInitialState()方法来初始化一些state.当这些完成后,会调用start()来start StateMachine. 等StateMachine初始化完毕后,从最父类型的state开始依次调用enter()。这个操作会在StateMachine的handler里面去执行而不是通过对象的调用。这个操作在所有message执行前完成。
例如:当执行mP1.enter 时,将会调用mS1.enter.最终,message 将会传递到StateMachine从而被当前的state去执行。在如下这个例子中,将会最终执行mS1.processMessage.
mP1 / \ mS2 mS1 ----> initial state
TO BE UPDATE
阅读全文
0 0
- Android Data Analyse(4)--StateMachine
- Android Data Analyse(4)--NetworkCapabilities
- Android Data Analyse(1)--ConnectivityManager
- Android Data Analyse(2)--ConnectivityService
- Android Data Analyse(3)--APN & ApnSetting & ApnContext
- android状态机机制StateMachine
- android状态机机制StateMachine
- Android StateMachine分析
- android状态机statemachine详解
- Android StateMachine和AsyncChannel
- android状态机statemachine详解
- android状态机机制StateMachine
- Android StateMachine和AsyncChannel
- Android StateMachine和AsyncChannel
- Android StateMachine 分析
- android状态机机制StateMachine
- android状态机statemachine详解
- Android StateMachine和AsyncChannel
- 防止android内存泄露的机制方式
- 互联网营销讨论社区
- 剑指offer之二维数组中的查找
- 初识C语言
- Linux应用编程基础--(3)文件库
- Android Data Analyse(4)--StateMachine
- SQL_过滤相邻数据重复项,筛选出。间隔的重复数据
- JSP
- TraceView工具如何使用
- android studio 导入jar包
- BZOJ 1529 [POI 2005] 并查集 解题报告
- python sys.argv是什么?
- 笔记 正则表达式
- T-Finder论文中IVMM算法的源码