StateMachine狀態機的介紹中,以下的這篇博客講得已經很全面了。
http://www.cnblogs.com/bastard/archive/2012/06/05/2536258.html
爲了更加方便的理解,個人簡單的畫了一張時序圖:
具體的使用:
要實現自己的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之間的關係圖:
代碼略.