Home IT Linux Windows Database Network Programming Server Mobile  
           
  Home \ Programming \ Android design patterns - state mode     - How to install and use the Snort in Ubuntu 15.04 (Linux)

- CentOS yum source configuration (Linux)

- Django template inheritance child (Programming)

- About Leetcode on Binary Tree Algorithm summary (Programming)

- MySQL to manage multiple instances of method (Database)

- How Linux Log Analysis (Linux)

- Docker startups use continuous integration deployment (Server)

- Linux folder and extract the differential file comparison techniques -rsync Magical (Linux)

- TNS-03505 name could not be resolved (Database)

- MySQL + Corosync + Pacemaker + DRBD build highly available MySQL (Server)

- Ubuntu 14.04 configure JDK1.8.0_25, switchable version (Linux)

- Nginx configuration support f4v video format player (Server)

- How to Create a file can not be changed under Linux (Linux)

- Joseph Central Java implementation (Programming)

- Making Linux root file system problems on-link library (Programming)

- Oracle 10g, 11g database silent installation of small differences (Database)

- MyCAT easy entry (Database)

- xCAT error Unable to dispatch hierarchical sub-command to NORESOLUTION: 3001 (Linux)

- Android Studio Personalization (Linux)

- Linux maximum number of threads and limit the number of queries the current thread (Linux)

 
         
  Android design patterns - state mode
     
  Add Date : 2016-12-24      
         
       
         
  Status Mode Description

"State Pattern allows an object to change its internal state to change its behavior when the object looked like a changed its class, like.." - "JAVA and model"
Managers hold a variety of state, after state switch, when the manager calls the Handle method indirectly call state class Handle method, thus depending on the current state, it can show different results.

State Pattern Example of use

For example, a transformer, it is assumed that there are 3 states: automobile state, humanoid state, condition of the aircraft. Different states to fight, when used in different ways, are "rolling strike," "unarmed" and "missile firing." Various classes and methods, see the following class diagram

Code

State Interface

public interface State {
    public void fight ();
}
CarState

public class CarState implements State {
    private static String stateName = "auto form";

    @Override
    public void fight () {
        System.out.println ( "rolling rampage");
    }


    @Override
    public String toString () {
        return stateName;
    }
}

FlightState

public class FlightState implements State {
    private static String stateName = "plane shape";
    @Override
    public void fight () {
        System.out.println ( "missile attack");
    }
    @Override
    public String toString () {
        return stateName;
    }
}

HumanState

public class HumanState implements State {
    private static String stateName = "humane form";
    @Override
    public void fight () {
        System.out.println ( "unarmed struggle");
    }
    @Override
    public String toString () {
        return stateName;
    }
}

Transformer type

public class Transformer {
    private String name;
    private State currentState;
    public State transformTo (State state) {
        this.currentState = state;
        return this.currentState;
    }
    public void fight () {
        this.currentState.fight ();
    }
    public Transformer (String name, State currentState) {
        this.name = name;
        this.currentState = currentState;
    }

}
Test category

public class TransformerTest {
     public static void main (String [] args) {
         State currentState;
         // Create the initial form
         State initState = new CarState ();
         // Create Transformers
         Transformer bumblebee = new Transformer ( "Hornet", initState);
         // Start fighting
         bumblebee.fight ();
         // Switch to humanoid form
         currentState = bumblebee.transformTo (new HumanState ());
         System.out.println ( "Switch to:" + currentState);
         bumblebee.fight ();
         // Switch to airplane configuration
         currentState = bumblebee.transformTo (new FlightState ());
         System.out.println ( "Switch to:" + currentState);
         bumblebee.fight ();
     }
}

Output

Rolling rampage
Switch to: human form
Unarmed struggle
Switch to: airplane configuration
Missile attack
Android source code of the Application Example

Android system source code, there is a utility class called StateMachine, the class is a hierarchical state machine, handle various conversions State class. State processMessage state class must implement method, in order to create / destroy the work environment can also inherit the implementation of enter / exit methods.

Compared between the aforesaid basic state mode, StateMachine can in each state, the definition of which receives different instructions, which will switch to state, without the need to take the initiative to set the state of the state machine, and reduces the body state coupling more convenient, to add a new state.

Establishment of the state machine

When a StateMachine object is created, it can addState () function to set the state of the state machine which, by setInitialState () to set the initial state. To initialize and start the virtual machine start () method.

addState (State state, State parent) ---- state for the current increase in the state, parent to parent of the current state.
When the first call state machine starts initial State's enter function to initialize the current state, and the beginning of the call from the parent state topmost, then down again to use sub-state enter.

        mP1
       / \
      mS2 mS1 ----> initial state
As shown above, when the initial state is set mS1 will in turn call mP1 mS1 enter the function to initialize the environment. The following code shows, mStateStack is a state StateInfo array from parent to child. StateInfo and a State is bound. Contains the current state of the parent state, is currently active.

        private final void invokeEnterMethods (int stateStackEnteringIndex) {
            for (int i = stateStackEnteringIndex; i < = mStateStackTopIndex; i ++) {
                if (mDbg) Log.d (TAG, "invokeEnterMethods:" + mStateStack [i] .state.getName ());
                mStateStack [i] .state.enter ();
                mStateStack [i] .active = true;
            }
        }
You can look at the initialization of the array:
1, followed by the first state of the current status and retroactive loop is stored in the parent class mTempStateStack temporary stack.

        private final void setupInitialStateStack () {
            if (mDbg) {
                Log.d (TAG, "setupInitialStateStack: E mInitialState ="
                    + MInitialState.getName ());
            }


            StateInfo curStateInfo = mStateInfo.get (mInitialState);
            for (mTempStateStackCount = 0; curStateInfo = null;! mTempStateStackCount ++) {
                mTempStateStack [mTempStateStackCount] = curStateInfo;
                curStateInfo = curStateInfo.parentStateInfo;
            }


            // Empty the StateStack
            mStateStackTopIndex = -1;


            moveTempStateStackToStateStack ();
        }
2, and then reverse the temporary stack and stored in mStateStack, and then start from zero mStateStack is the topmost parent class, and then click Save subclasses.

        private final int moveTempStateStackToStateStack () {
            int startingIndex = mStateStackTopIndex + 1;
            int i = mTempStateStackCount - 1;
            int j = startingIndex;
            while (i> = 0) {
                if (mDbg) Log.d (TAG, "moveTempStackToStateStack: i =" + i + ", j =" + j);
                mStateStack [j] = mTempStateStack [i];
                j + = 1;
                i - = 1;
            }


            mStateStackTopIndex = j - 1;
            if (mDbg) {
                Log.d (TAG, "moveTempStackToStateStack: X mStateStackTop ="
                      + MStateStackTopIndex + ", startingIndex =" + startingIndex
                      + ", Top =" + mStateStack [mStateStackTopIndex] .state.getName ());
            }
            return startingIndex;
        }
The state machine is running

After the state machine starts, obtained by invoking the state machine StateMachine.obtainMessage () message function to send messages through StateMachine.sendMessage () function, after the state receives this message, it will call processMessage current state () function according to the current state defined manner, to switch states.

        public final void handleMessage (Message msg) {
            if (mDbg) Log.d (TAG, "handleMessage: E msg.what =" + msg.what);


            / ** Save the current message * /
            mMsg = msg;


            if (mIsConstructionCompleted) {
                / ** Normal path * /
                processMsg (msg);
                ......

        private final void processMsg (Message msg) {
            StateInfo curStateInfo = mStateStack [mStateStackTopIndex];
            if (mDbg) {
                Log.d (TAG, "processMsg:" + curStateInfo.state.getName ());
            }


            if (isQuit (msg)) {
                transitionTo (mQuittingState);
            } Else {
                while (! curStateInfo.state.processMessage (msg)) {// call the current state processMessage () function
                    curStateInfo = curStateInfo.parentStateInfo; // if the current state does not deal with, then the parent status to the current state to continue the parent state ProcessMessage function processing
                    if (curStateInfo == null) {// If the state no longer has a parent, then as unprocessed Print Log
                        mSm.unhandledMessage (msg);
                        break;
                    }
                    if (mDbg) {
                        Log.d (TAG, "processMsg:" + curStateInfo.state.getName ());
                    }
                }
The state of the state machine, there may be a parent state, if the current state of processMessage function returns false or NOT_HANDLED, the parent will be called up processMessage function state is processed, if the top of the parent state is not treated, it handed unhandledMessage final processing function (generally lose, of course, you can define your own final processing function). Then

When all the processing is finished, the state machine can call transitionToHaltingState enter HaltingState (StateMachine internal default state). And calls to a custom StateMachine of onHalting () function, after entering HaltingState state, all subsequent messages sent, will lead the call HaltingState haltedProcessMessage (also need to inherit implement custom processing).

If you want to stop state machine, you can call the quit or abort method to enter QuittingState, and the next process, quit HandlerThread thread, cleaning inside each object.

Conversion status will lead to entry and exit, and the new state of the current state when you exit from the current state, the state will call the parent layer by layer up exit exit function, but noted that this layer by layer is called, the current status and objectives co-parent status at the state no longer execute exit (), if there is no common parent state before the state and the target state, is completely out of the current state of all the parent state and enters a new state.

        private final void invokeExitMethods (StateInfo commonStateInfo) {// commonStateInfo co-parent status before state and target state
            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;
            }
        }
The state machine can also call deferMessage method and sendMessageAtFrontOfQueue methods.
deferMessage method stores the message in a queue delay in this case is not sent out, but the next time the state transition time (for example, from the state to the B state A), the delay queue of all messages in the message the head of the queue. These messages will be in the B state as the current state is processed.
sendMessageAtFrontOfQueue method calls the state machine of sendMessageAtFrontOfQueue Handler () method, the current message is sent, at the top instead of the original rearmost message queue.
To illustrate these characteristics, the following is a state with eight state level.

          mP0
         / \
        mP1 mS0
       / \
      mS2 mS1
     / \ \
    mS3 mS4 mS5 ---> initial state
When the state machine starts, enters the initial state mS5, each parent status is also active, then mP0, mP1, mS1 and mS5 are active. When a message is sent to, will in turn call mS5,
mS1, mP1, mP0 of processMessage method (the premise is false returns or NOT_HANDLED).
And now suppose mS5 of processMessage can process the message, and calls transitionTo (mS4) will state to mS4, then return true or HANDLED. processMessage will enter after returning performTransitions method will find a common parent status mS5 and mS4, which is mP1. Then turn calls mS5.exit, mS1.exit then mS2.enter mS4.enter. Then mP0, mP1, mS2, mS4 four states is active, the moment when a message arrives, it will activate mS4. processMessage methods.

Here is an inherited StateMachine of HelloWorld. In this state the opportunity to receive a message each time a print "Hello World" string.

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
Here is a state with four state machine, and is divided into two separate parent state

        mP1 mP2
       / \
      mS2 mS1-- initial state
Here is the pseudo code several states

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;
     }
}
Test code:

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");


        // Add state
        addState (mP1);
            addState (mS1, mP1);
            addState (mS2, mP1);
        addState (mP2);


        // Set the initial state
        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 do not 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 ();
}




// Note: Adding synchronize block is because we use hsm.wait ().
Hsm1 hsm = makeHsm1 (); // create an object 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 ());
     }
}
Output:

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

Examples -DataConnection state machine

Android source code used in many places the state machine, such as Wifi status, data link status, Bluetooth headset status, we take the typical Telephony in DataConnection (Android4.2.2) as an example of using a state machine.

DcDefaultState which is the parent state of all states,

Status Meaning
DcInactiveState inactive
DcActivatingState active
DcActiveState active
DcDisconnectingState deactivated state
When you create a connection error status DcDisconnectionErrorCreatingConnection

initialization

    protected DataConnection (PhoneBase phone, String name, int id, RetryManager rm,
            DataConnectionTracker dct) {
            ......
        addState (mDefaultState);
            addState (mInactiveState, mDefaultState);
            addState (mActivatingState, mDefaultState);
            addState (mActiveState, mDefaultState);
            addState (mDisconnectingState, mDefaultState);
            addState (mDisconnectingErrorCreatingConnection, mDefaultState);
        setInitialState (mInactiveState);
        ....
Beginning in DcInactiveState state, DataConnectionTracker call DataConnection method when the bringUp

    public void bringUp (Message onCompletedMsg, ApnSetting apn) {
        sendMessage (obtainMessage (EVENT_CONNECT, new ConnectionParams (apn, onCompletedMsg)));
    }
EVENT_CONNECT sends a message, which will be called the current state of processMessage DcInactiveState method.

        public boolean processMessage (Message msg) {
            boolean retVal;


            switch (msg.what) {
                case EVENT_CONNECT:
                    ConnectionParams cp = (ConnectionParams) msg.obj;
                    cp.tag = mTag;
                    if (DBG) {
                        log ( "DcInactiveState msg.what = EVENT_CONNECT." + "RefCount ="
                                + MRefCount);
                    }
                    mRefCount = 1;
                    onConnect (cp); // call the method phone.mCM.setupDataCall want RILJ send RIL_REQUEST_SETUP_DATA_CALL request.
                    transitionTo (mActivatingState); // switch to mActivatingState state.
                    retVal = HANDLED;
                    break;
The switching process can read other states according to their own needs and interests.
     
         
       
         
  More:      
 
- Java polymorphism and exception handling (Programming)
- How to update the Linux kernel to improve system performance (Linux)
- Linux system - The understanding cpu load (Linux)
- PXE installation of Linux servers (Server)
- Use the vi text editor and copy and paste Linux tips (Linux)
- Understand the profound discussion of some of the options for wireless encryption (Linux)
- Arronax allows you to easily create desktop startup file (Linux)
- MariaDB 10.0.X, the dynamic column support JSON format to obtain data (Database)
- MySQL Parameter Tuning Best Practices (Database)
- CentOS 6.5 system installation Oracle11.2.0.4 basic steps (Database)
- Android engineers interview questions (Programming)
- RAID configuration and management under linux (Server)
- Let MySQL 5.6 support Emoji expression (Database)
- Recovery from MySQL master data consistency summary (Database)
- Oracle create a temporary table space group (Database)
- CentOS 7 Add yum source (Linux)
- Linux initialization init system - UpStart (Linux)
- MySQL stored procedures execute dynamic sql statement (Database)
- Open SSH remote access service that allows Android phone Ubuntu 14.04 (Linux)
- Linux common network tools: ping host sweep (Linux)
     
           
     
  CopyRight 2002-2016 newfreesoft.com, All Rights Reserved.