Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1501076
  • 博文数量: 218
  • 博客积分: 6394
  • 博客等级: 准将
  • 技术积分: 2563
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-08 15:33
个人简介

持之以恒

文章分类

全部博文(218)

文章存档

2013年(8)

2012年(2)

2011年(21)

2010年(55)

2009年(116)

2008年(16)

分类: Android平台

2013-02-16 18:08:41

参考:http://www.cnblogs.com/bastard/archive/2012/06/05/2536258.html 

一 State模式

(I) 意图:

  允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。(Objects for States)对象内部状态决定行为方式,对象状态改变行为方式改变;State模式是将对象的状态封装成一个对象,是在不同的状态下同样的调用执行不同的操作

(II) 适用性:

  (1) 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态来改变行为;

  (2) 一个操作中含有庞大的多分支条件语句,且这些分支依赖于该对象的状态;

解决方法: 将分支语句放入一个类中进行处理,即将对象的状态封装成为一个独立对象;

(III) 结构:


       Context:维护一个State的子类实例,这个实例定义当前的状态;


State:定义一个接口以封装与Context的一个特定状态相关的行为;

Context与State交互:
  (1) Context将与状态相关的请求委托给当前的ConcreteState处理;
  (2) Context可将自身作为一个参数传递给处理该请求的状态,使得状态对象在必要的时访问Context;
  (3) Context是客户使用的主要接口,客户可用对象来配置一个Context,一旦一个Context配置完毕,它的客户不再需要直接与状态对象打交道;
  (4) Context或ConcreteState子类都可以决定哪个状态是另外哪一个的后继者,以及是在何种条件下进行转换;

 (IV)问题:状态切换如何进行管理?

二 Android中StateMachine机制

(I)状态机

定义:It is conceived as an abstract machine that can be in one of a finite number of states. The machine is in only one state at a time; the state it is in at any given time is called the current state. It can change from one state to another when initiated by a triggering event or condition; this is called a transition. A particular FSM is defined by a list of its states, and the triggering condition for each transition.

普通状态机存在的问题:实践中状态机有一个致命的缺点,当状态一旦多了之后,它的跳转就会变的不可维护,假设有n个状态的话,那我们就需要维护最多n*n的跳转链接(因为状态机允许自己跳转自己),而且对于当前处在的状态而言,我不能知道我的跳转历史,也就是说,我很难知道为什么我会在这个状态里。

(II)层次状态机

如果用层次化的状态机的话,我们就先会把这些行为“分类”,把几个小状态归并到一个状态里,然后再定义高层状态和高层状态中内部小状态的跳转链接。



三 Android 中StateMachine模块分析

主要接口

(1) 状态机

public final void sendMessage(int what)

public final void quit()

public void start()

protected final void deferMessage(Message msg)

protected final void transitionTo(HierarchicalState destState)

(2) 状态

public class State implements IState
{
  protected State() {}
  public void enter() {}
  public void exit() {}
  public boolean processMessage(Message msg) {}
  public String getName() {}
}


1 State Machine各个模块作用

    SmHandle是构建StateMachine的核心。初始化过程:
 
  1.  protected HierarchicalStateMachine(String name) {  
  2.         mHsmThread = new HandlerThread(name);  
  3.         mHsmThread.start();  
  4.         Looper looper = mHsmThread.getLooper();  
  5.         initStateMachine(name, looper);  
  6.     }  
     
    		
    1.  
      				
      1.  
        						
        1.  
 
 
private void initStateMachine(String name, Looper looper) {  
        mName = name;  
        mHsmHandler = new HsmHandler(looper, this);  
    } 


 
运行在独立的线程上,有三个功能:
 
(1)建立树形层次结构存储State; 
(2)消息处理和派发  
 
(3)状态机的StateStack建立和状态切换;

 
 
 
 

(1) 建立树形存储结构

例如:     SmHandle sm;   sm.addState(S0,null);   sm.addState(S1,S0);   sm.addState(S2,S0);   sm.addState(S3,S1);   sm.addState(S4,S1);   sm.addState(S5,S2);   sm.addState(S6,S2);   sm.addState(S7,S2);   setInitialState(S4);      //设置初始状态

    (2)  处理消息
public final void handleMessage(Message msg) { /** * Process the message abiding by the hierarchical semantics * and perform any requested transitions. */ processMsg(msg); performTransitions(); }
 
        /** 
         * Process the message. If the current state doesn't handle 
         * it, call the states parent and so on. If it is never handled then 
         * call the state machines unhandledMessage method. 
         */  
        private final void processMsg(Message msg) {  
            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];  
            while (!curStateInfo.state.processMessage(msg)) {  
                /** 
                 * Not processed 
                 */  
                curStateInfo = curStateInfo.parentStateInfo;  
                if (curStateInfo == null) {  
                    /** 
                     * No parents left so it's not handled 
                     */  
                    mHsm.unhandledMessage(msg);  
                    break;  
                }  
            }  
        }  
处理状态变化:
 
private final void transitionTo(IState destState) {                              
// destState为要处理的State(Message)
            mDestState = (State) destState;
            if (mDbg) Log.d(TAG, "StateMachine.transitionTo EX destState" + mDestState.getName());
        }
 
S5-->S3
private synchronized void performTransitions() 
{
  while (mDestState != null)
  {
    //当前状态切换了 存在于mStateStack中的State需要改变
    //仍然按照链式父子关系来存储
    //先从当前状态S3找到 最近的被激活的parent状态S0
    //未被激活的全部保存起来(S3,S1) 返回S0
    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);

    //将mStateStack中 不属于当前状态(S3),
    //关系链上的State(S5,S2)退出(执行exit方法)
    invokeExitMethods(commonStateInfo);

    //将S3关系链 加入到栈中(S3,S1)
    int stateStackEnteringIndex = moveTempStateStackToStateStack();

    //将新加入到mStateStack中 未被激活的State激活(S3,S1)
    invokeEnterMethods(stateStackEnteringIndex);

    //将延迟的消息移动到消息队列的前面,以便快速得到处理               
    moveDeferredMessageAtFrontOfQueue();
  }
}

1.  StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState(S3));  逐次向上查找destState的所有祖先直到该祖先的stateInfo.Active为true(S0)才停止,并将值放到mTempStateStake [S3 S1] 里面,树根对应下标最大的,commonstateInfo[S0]为该祖先的stateInfo属性,在这个函数里面也将mTempStateStake清空了,并重新赋值了。

2.invokeExitMethods(commonStateInfo)方法从mStateStack的顶部依次向下移动直到找到commonStateInfo,把这些之间的state[S5 S2]的exit方法都执行,并将Active赋值为false。

3.int stateStackEnteringIndex = moveTempStateStackToStateStack()将mTempStateStack[]数组的值倒序付 给了mStateStack数组并且设置了 mStateStackTopIndex(栈顶序列号)的值为数组的最大下标。

4. invokeEnterMethods(stateStackEnteringIndex);   从stateStackEnteringIndex向栈顶依次执行enter方法并设Active为true

实例研究:



 * The implementation is below and also in HierarchicalStateMachineTest: 
 
class Hsm1 extends HierarchicalStateMachine { 
    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"); 
 
        // Add states, use indentation to show hierarchy 
        addState(mP1); 
            addState(mS1, mP1); 
            addState(mS2, mP1); 
        addState(mP2); 
 
        // Set the initial state 
        setInitialState(mS1); 
        Log.d(TAG, "ctor X"); 
    } 
 
    class P1 extends HierarchicalState { 
        @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 HierarchicalState { 
        @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 HierarchicalState { 
        @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 HierarchicalState { 
        @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 halting() { 
        Log.d(TAG, "halting"); 
        synchronized (this) { 
            this.notifyAll(); 
        } 
    } 
 
    P1 mP1 = new P1(); 
    S1 mS1 = new S1(); 
    S2 mS2 = new S2(); 
    P2 mP2 = new P2(); 
} 
 
 * 
 * If this is executed by sending two messages CMD_1 and CMD_2 
 * (Note the synchronize is only needed because we use hsm.wait()) 
 * 
 * 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) { 
 *           Log.e(TAG, "exception while waiting " + e.getMessage()); 
 *      } 
 * } 
 * 
 * 
 * The output is: 
 * 
 * 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 
疯狂的火星虫 


阅读(7746) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~