StateMachine狀態機初識

StateMachine狀態機的介紹中,以下的這篇博客講得已經很全面了。
http://www.cnblogs.com/bastard/archive/2012/06/05/2536258.html

爲了更加方便的理解,個人簡單的畫了一張時序圖:

StateMachine狀態機

具體的使用:

要實現自己的StateMachine並讓它跑起來,需要做以下幾個工作:
一 . 實現自己的State子類。
StateMachine已經幫我們做了大部分工作,現在每當一個事件消息進到State子類的時候,會按順序執行enter()–>processMessage()–>exit()。當然,這個順序是在State之間不互相跳轉的情況下,如果在enter()或者processMessage()的時候跳轉到其他的State,則會執行其他State的enter()–>processMessage()–>exit()。

public class State implements IState {
    @Override
    public void enter() {
    }
    @Override
    public void exit() {
    }  
    @Override
    public boolean processMessage(Message msg) {
        return false;
    }   
}   

二 . 把自己的State加入到StateMachine中,並設置默認的State。
見時序圖的addState(),setInitialState()。
三 . 啓動StateMachine。
見時序圖start()。這個時候狀態機已經跑起來了,樹形層次結構存儲State和狀態機的StateStack都已經建立好。
四 . 派發事件消息。
使用者需要通過sendMessage()派發事件消息,這個事件消息的處理,會先由默認的State處理,如果它處理得過來,就return,如果處理不過來,那就跳轉到別的State來處理。這些邏輯都需要在自定義的State中設置好,所以要實現自己的StateMachine,自定義的State之間的事件消息的處理和各個State之間的跳轉關係尤爲重要。

例子1

使用者:DcAsyncChannel.java
狀態機:DataConnection.java

各個State的繼承者:
DcDefaultState
DcInactiveState
DcInactiveState
DcActiveState
DcDisconnectingState
DcDisconnectionErrorCreatingConnection

各個State之間的關係圖:
這裏寫圖片描述

DataConnection.java中的自定義State實現,以下只列出兩個State及其部分代碼:

private class DcActiveState extends State {
    ...
    public boolean processMessage(Message msg) {
       switch (msg.what) {
           case EVENT_CONNECT:......
           case EVENT_DISCONNECT: transitionTo(mDisconnectingState);......
           case EVENT_LOST_CONNECTION: transitionTo(mInactiveState);......
           case EVENT_DATA_CONNECTION_ROAM_ON:......
           case EVENT_DATA_CONNECTION_ROAM_OFF:......
           case EVENT_BW_REFRESH_RESPONSE:......
           case EVENT_IPV4_ADDRESS_REMOVED:......
           case EVENT_IPV6_ADDRESS_REMOVED:......
           case EVENT_VOICE_CALL:......
           case EVENT_FALLBACK_RETRY_CONNECTION:......
           case EVENT_SETUP_DATA_CONNECTION_DONE:......
       }
    }
}
private class DcDefaultState extends State {
    switch (msg.what) {
        case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: 
        case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
        case DcAsyncChannel.REQ_IS_INACTIVE: 
        case DcAsyncChannel.REQ_GET_CID:
        case DcAsyncChannel.REQ_GET_APNSETTING:
        case DcAsyncChannel.REQ_GET_APNTYPE: 
        case DcAsyncChannel.REQ_GET_LINK_PROPERTIES:
        case DcAsyncChannel.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: 
        case DcAsyncChannel.REQ_GET_NETWORK_CAPABILITIES:
        case DcAsyncChannel.REQ_RESET: transitionTo(mInactiveState);
        case EVENT_CONNECT:
        case EVENT_DISCONNECT: deferMessage(msg);
        case EVENT_DISCONNECT_ALL: deferMessage(msg);
        case EVENT_TEAR_DOWN_NOW:
        case EVENT_LOST_CONNECTION:
        case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
        case EVENT_DATA_CONNECTION_ROAM_ON:
        case EVENT_DATA_CONNECTION_ROAM_OFF:
        case EVENT_IPV4_ADDRESS_REMOVED:
        case EVENT_IPV6_ADDRESS_REMOVED:
        case EVENT_ADDRESS_REMOVED:
        case EVENT_VOICE_CALL:
    }
}

DataConnection.java中把State加入到StateMachine,並設置默認State

addState(mDefaultState);
    addState(mInactiveState, mDefaultState);
    addState(mActivatingState, mDefaultState);
    addState(mActiveState, mDefaultState);
    addState(mDisconnectingState, mDefaultState);
    addState(mDisconnectingErrorCreatingConnection, mDefaultState);
setInitialState(mInactiveState);
dc.start();

DcAsyncChannel.java中發起事件消息:

sendMessage(DataConnection.EVENT_CONNECT,
        new ConnectionParams(apnContext, profileId, rilRadioTechnology, onCompletedMsg,
                connectionGeneration));
sendMessage(DataConnection.EVENT_DISCONNECT,
                new DisconnectParams(apnContext, reason, onCompletedMsg));
sendMessage(DataConnection.EVENT_DISCONNECT_ALL,
        new DisconnectParams(null, reason, onCompletedMsg));
sendMessage(DataConnection.EVENT_VOICE_CALL, bInVoiceCall ? 1 : 0,
        bSupportConcurrent ? 1 : 0);

可以在radio.log中看到它們狀態之間的跳轉:

08-12 19:02:52.465863  1134  1399 D DC-1    : DcDefaultState: FULL_CONNECTION reply connected
08-12 19:02:52.477583  1134  1399 D DC-1    : DcInactiveState: msg.what=EVENT_CONNECT
08-12 19:02:52.661152  1134  1399 D DC-1    : DcActivatingState: msg={what=EVENT_SETUP_DATA_CONNECTION_DONE when=-1ms obj=android.os.AsyncResult@d340de4 target=Handler (com.android.internal.util.StateMachine$SmHandler) {dbd924d} replyTo=null}
08-12 19:03:23.140182  1134  1399 D DC-1    : DcActiveState msg.what=EVENT_DISCONNECT RefCount=1
08-12 19:03:23.290534  1134  1399 D DC-1    : DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount=0
08-12 19:03:23.332824  1134  1399 D DC-1    : DcInactiveState nothandled msg.what=EVENT_IPV4_ADDRESS_REMOVED

例子2

使用者:ConnectivityService.java
狀態機:NetworkMonitor.java

各個State的繼承者:
DefaultState 默認狀態
EvaluatingState 驗證狀態
ValidatedState 驗證通過狀態
LingeringState 休閒狀態,表示網絡的驗證位是真實的,並且曾經是滿足特定NetworkRequest的最高得分網絡,但是此時另一個網絡滿足了NetworkRequest的更高分數,在斷開連接前的一段時間前,該網絡被“固定”爲休閒狀態。
CaptivePortalState 強制門戶狀態
MaybeNotifyState 可能通知狀態,表示用戶可能已被通知需要登錄。 在退出該狀態時,應該小心清除通知。

各個State之間的關係圖:
這裏寫圖片描述

代碼略.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章