StateMachine状态机初识

来源:互联网 发布:淘宝客佣金5元怎么设置 编辑:程序博客网 时间:2024/06/15 19:35

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 connected08-12 19:02:52.477583  1134  1399 D DC-1    : DcInactiveState: msg.what=EVENT_CONNECT08-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=108-12 19:03:23.290534  1134  1399 D DC-1    : DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount=008-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之间的关系图:
这里写图片描述

代码略.

原创粉丝点击