FileDocCategorySizeDatePackage
HandlerStateMachine.javaAPI DocAndroid 1.5 API9572Wed May 06 22:41:56 BST 2009android.os

HandlerStateMachine

public class HandlerStateMachine extends Object
{@hide} Implement a state machine where each state is an object, HandlerState. Each HandlerState must implement processMessage and optionally enter/exit. When a state machine is created the initial state must be set. When messages are sent to a state machine the current state's processMessage method is invoked. If this is the first message for this state the enter method is called prior to processMessage and when transtionTo is invoked the state's exit method will be called after returning from processMessage. If a message should be handled in a different state the processMessage method may call deferMessage. This causes the message to be saved on a list until transitioning to a new state, at which time all of the deferred messages will be put on the front of the state machines queue and processed by the new current state's processMessage method. Below is an example state machine with two state's, S1 and S2. The initial state is S1 which defers all messages and only transition to S2 when message.what == TEST_WHAT_2. State S2 will process each messages until it receives TEST_WHAT_2 where it will transition back to S1: class StateMachine1 extends HandlerStateMachine { private static final int TEST_WHAT_1 = 1; private static final int TEST_WHAT_2 = 2; StateMachine1(String name) { super(name); setInitialState(mS1); } class S1 extends HandlerState {
Override
public void enter(Message message) { }
Override
public void processMessage(Message message) { deferMessage(message); if (message.what == TEST_WHAT_2) { transitionTo(mS2); } }
Override
public void exit(Message message) { } } class S2 extends HandlerState {
Override
public void processMessage(Message message) { // Do some processing if (message.what == TEST_WHAT_2) { transtionTo(mS1); } } } private S1 mS1 = new S1(); private S2 mS2 = new S2(); }

Fields Summary
private boolean
mDbg
private static final String
TAG
private String
mName
private SmHandler
mHandler
private HandlerThread
mHandlerThread
Constructors Summary
public HandlerStateMachine(String name)
Create an active StateMachine, one that has a dedicated thread/looper/queue.

        mName = name;
        mHandlerThread =  new HandlerThread(name);
        mHandlerThread.start();
        mHandler = new SmHandler(mHandlerThread.getLooper());
    
Methods Summary
public final voiddeferMessage(Message msg)
Defer this message until next state transition. Upon transitioning all deferred messages will be placed on the queue and reprocessed in the original order. (i.e. The next state the oldest messages will be processed first)

        if (mDbg) {
            Log.d(TAG, "StateMachine.deferMessage EX mDeferredMessages="
                            + mHandler.mDeferredMessages);
        }

        /* Copy the "msg" to "newMsg" as "msg" will be recycled */
        Message newMsg = obtainMessage();
        newMsg.copyFrom(msg);

        /* Place on front of queue */
        newMsg.next = mHandler.mDeferredMessages;
        mHandler.mDeferredMessages = newMsg;
    
public HandlergetHandler()

return
Handler

        return mHandler;
    
public java.lang.StringgetName()

return
the name

        return mName;
    
public booleanisDbg()

return
if debugging is enabled

        return mDbg;
    
public final MessageobtainMessage()
Get a message and set Message.target = this.

        Message msg = Message.obtain(mHandler);
        if (mDbg) Log.d(TAG, "StateMachine.obtainMessage() EX target=" + msg.target);
        return msg;
    
public final MessageobtainMessage(int what)
Get a message and set Message.target = this and Message.what = what.

        Message msg = Message.obtain(mHandler, what);
        if (mDbg) {
            Log.d(TAG, "StateMachine.obtainMessage(what) EX what=" + msg.what +
                       " target=" + msg.target);
        }
        return msg;
    
public final voidsendMessage(Message msg)
Enqueue a message to this state machine.

        if (mDbg) Log.d(TAG, "StateMachine.sendMessage EX msg.what=" + msg.what);
        mHandler.sendMessage(msg);
    
public final voidsendMessageDelayed(Message msg, long delayMillis)
Enqueue a message to this state machine after a delay.

        if (mDbg) {
            Log.d(TAG, "StateMachine.sendMessageDelayed EX msg.what="
                            + msg.what + " delay=" + delayMillis);
        }
        mHandler.sendMessageDelayed(msg, delayMillis);
    
public voidsetDbg(boolean dbg)
Set debug enable/disabled.

        mDbg = dbg;
        if (mDbg) {
            mHandlerThread.getLooper().setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
        } else {
            mHandlerThread.getLooper().setMessageLogging(null);
        }
   
public voidsetInitialState(HandlerState initialState)
Set the initial state. This must be invoked before and messages are sent to the state machine.

        if (mDbg) {
            Log.d(TAG, "StateMachine.setInitialState EX initialState"
                            + initialState.getClass().getName());
        }
        mHandler.mDestState = initialState;
    
public final voidtransitionTo(HandlerState destState)
transition to destination state. Upon returning from processMessage the current state's exit will be executed and upon the next message arriving destState.enter will be invoked.

        if (mDbg) {
            Log.d(TAG, "StateMachine.transitionTo EX destState"
                            + destState.getClass().getName());
        }
        mHandler.mDestState = destState;