日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android中的设计模式-状态模式

發(fā)布時間:2025/4/16 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android中的设计模式-状态模式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文出處:http://www.linuxidc.com/Linux/2015-04/116013.htm

狀態(tài)模式說明

“狀態(tài)模式允許一個對象在其內(nèi)部狀態(tài)改變的時候改變其行為。這個對象看上去就像是改變了它的類一樣。” –《JAVA與模式》
管理者持有多種狀態(tài),狀態(tài)切換后,管理者調(diào)用Handle方法時,間接調(diào)用狀態(tài)類中的Handle方法,從而根據(jù)當(dāng)前狀態(tài)的不同,就可以表現(xiàn)出不同的結(jié)果。

狀態(tài)模式類圖

狀態(tài)模式使用示例

例如一個變形金剛,假設(shè)它有3中狀態(tài):汽車狀態(tài),人形狀態(tài),飛機狀態(tài)。 不同的狀態(tài)進行戰(zhàn)斗的時候,采用的方式不同,分別是“撞擊碾壓”,“赤手空拳”和“導(dǎo)彈射擊”。各個類及方法見下面類圖

代碼

State接口

public interface State {public void fight(); }

CarState

public class CarState implements State {private static String stateName ="汽車形態(tài)";@Overridepublic void fight() {System.out.println("橫沖直撞碾壓");}@Overridepublic String toString() {return stateName;} }

FlightState

public class FlightState implements State {private static String stateName ="飛機形態(tài)";@Overridepublic void fight() {System.out.println("發(fā)射導(dǎo)彈攻擊");}@Overridepublic String toString() {return stateName;} }

HumanState

public class HumanState implements State {private static String stateName ="人性形態(tài)";@Overridepublic void fight() {System.out.println("赤手空拳搏斗");}@Overridepublic String toString() {return stateName;} }

Transformer類

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;}}

測試類

public class TransformerTest {public static void main(String[] args){State currentState;//創(chuàng)建初始形態(tài)State initState=new CarState();//創(chuàng)建變形金剛Transformer bumblebee= new Transformer("大黃蜂", initState);//開始戰(zhàn)斗bumblebee.fight();//切換到人形形態(tài)currentState= bumblebee.transformTo(new HumanState());System.out.println("切換到:"+currentState);bumblebee.fight();//切換到飛機形態(tài)currentState= bumblebee.transformTo(new FlightState());System.out.println("切換到:"+currentState);bumblebee.fight();} }

輸出結(jié)果

橫沖直撞碾壓 切換到:人性形態(tài) 赤手空拳搏斗 切換到:飛機形態(tài) 發(fā)射導(dǎo)彈攻擊

Android源碼中的使用舉例

Android系統(tǒng)源代碼中有一個名為StateMachine的工具類,該類是一個分層狀態(tài)機,處理各種State類的轉(zhuǎn)化。State狀態(tài)類必須實現(xiàn)processMessage方法,為了創(chuàng)建/摧毀工作環(huán)境,還可以繼承實現(xiàn)enter/exit等方法。

相比較前面所說的基本的狀態(tài)模式,StateMachine可以在每一個狀態(tài)內(nèi),定義其接收不同的指令,會切換到哪個狀態(tài),而不需要狀態(tài)機主動去設(shè)定狀態(tài),降低了主體和狀態(tài)之間的耦合,增加一個新狀態(tài)時更加方便。

狀態(tài)機建立

當(dāng)一個StateMachine對象建立后,可以通過addState()函數(shù)來設(shè)定狀態(tài)機有哪些狀態(tài),通過setInitialState()來設(shè)定初始的狀態(tài)。通過start()方法來初始化并啟動虛擬機。

addState(State state, State parent) —-state為當(dāng)前增加的狀態(tài),parent為當(dāng)前狀態(tài)的父狀態(tài)。
狀態(tài)機啟動時首先調(diào)用初始State的enter函數(shù)來初始化當(dāng)前狀態(tài),并且是從最頂層的父狀態(tài)開始調(diào)用,然后再向下調(diào)用到子狀態(tài)的enter。

mP1/ \mS2 mS1 ----> initial state

如上所示,當(dāng)設(shè)定mS1為初始狀態(tài)時,會依次調(diào)用mP1 mS1的enter函數(shù)來初始化環(huán)境。如下代碼所展示的,mStateStack是狀態(tài)從父到子的一個StateInfo數(shù)組。StateInfo是和一個State綁定的。包含了當(dāng)前狀態(tài),父狀態(tài),當(dāng)前是否激活。

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;}}

可以看看這個數(shù)組的初始化過程:
1,首先依次把當(dāng)前狀態(tài)及循環(huán)追溯父類的狀態(tài)保存在mTempStateStack臨時的棧中。

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 StateStackmStateStackTopIndex = -1;moveTempStateStackToStateStack();}

2,然后把臨時的棧倒序,并保存在mStateStack中,這時mStateStack從0開始就是最頂端的父類,然后依次保存子類。

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;}

狀態(tài)機運行

狀態(tài)機啟動之后,通過調(diào)用狀態(tài)機的StateMachine.obtainMessage()函數(shù)來獲取消息,通過StateMachine.sendMessage()函數(shù)來發(fā)送消息,狀態(tài)機接收到這個消息后,就會調(diào)用當(dāng)前狀態(tài)的processMessage()函數(shù)來根據(jù)當(dāng)前狀態(tài)中定義好的方式,進行狀態(tài)的切換。

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)) { //調(diào)用當(dāng)前狀態(tài)的processMessage()函數(shù)curStateInfo = curStateInfo.parentStateInfo;//如果當(dāng)前狀態(tài)沒有處理,則將父狀態(tài)設(shè)為當(dāng)前狀態(tài),繼續(xù)父狀態(tài)的ProcessMessage函數(shù)處理if (curStateInfo == null) {//如果不再有父狀態(tài)了,則作為未處理的信息打印LogmSm.unhandledMessage(msg);break;}if (mDbg) {Log.d(TAG, "processMsg: " + curStateInfo.state.getName());}}

狀態(tài)機中的狀態(tài),可能會有父狀態(tài),如果當(dāng)前狀態(tài)的processMessage函數(shù)返回false 或者 NOT_HANDLED,就會向上調(diào)用父狀態(tài)的processMessage函數(shù)進行處理,如果最頂端的父狀態(tài)也沒處理,那就交給unhandledMessage函數(shù)做最后的處理(一般是丟掉,當(dāng)然可以自己定義最后的處理函數(shù))。隨后

當(dāng)所有的處理結(jié)束后,狀態(tài)機可以調(diào)用transitionToHaltingState進入HaltingState(StateMachine內(nèi)部預(yù)設(shè)的狀態(tài))。并調(diào)用到自定義StateMachine的onHalting()函數(shù),進入HaltingState狀態(tài)后,所有隨后發(fā)來的消息,都會導(dǎo)致HaltingState的haltedProcessMessage的調(diào)用(同樣需要繼承實現(xiàn)自定義處理)。

如果想要停止?fàn)顟B(tài)機,可以調(diào)用quit或者abort方法,從而進入QuittingState,并在下一次處理時,退出HandlerThread線程,清理內(nèi)部各個對象。

狀態(tài)的轉(zhuǎn)換會導(dǎo)致當(dāng)前狀態(tài)的退出,和新狀態(tài)的進入,當(dāng)從當(dāng)前狀態(tài)退出時,會逐層向上調(diào)用父狀態(tài)的退出exit函數(shù),但注意,這種逐層調(diào)用,會在當(dāng)前狀態(tài)和目標(biāo)狀態(tài)的共同父狀態(tài)處不再執(zhí)行exit(),如果前狀態(tài)和目標(biāo)狀態(tài)的不存在共同的父狀態(tài),則徹底退出當(dāng)前狀態(tài)的所有父狀態(tài),并進入新狀態(tài)。

private final void invokeExitMethods(StateInfo commonStateInfo) {//commonStateInfo是前狀態(tài)和目標(biāo)狀態(tài)的共同父狀態(tài)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;} }

狀態(tài)機還可以調(diào)用deferMessage方法和sendMessageAtFrontOfQueue方法。

deferMessage方法會將該消息保存在一個延遲隊列中,這時并不發(fā)送出去,而是會在下一次狀態(tài)轉(zhuǎn)變的時候(例如從A狀態(tài)變?yōu)锽狀態(tài)),將延遲隊列中的所有消息放在消息隊列的最前面。這些消息就會在B狀態(tài)作為當(dāng)前狀態(tài)時被處理。

sendMessageAtFrontOfQueue方法會調(diào)用狀態(tài)機的Handler的sendMessageAtFrontOfQueue()方法,將當(dāng)前發(fā)送的消息,排在消息隊列的最前面而不是原本的最后面。

為了說明這些特性,下面是一個具有8個狀態(tài)的狀態(tài)層次。

mP0/ \mP1 mS0/ \mS2 mS1/ \ \ mS3 mS4 mS5 ---> 初始狀態(tài)

當(dāng)狀態(tài)機開始后,進入初始狀態(tài)mS5,各個父狀態(tài)同樣也是活動的,于是mP0, mP1, mS1 和mS5都是活動的。當(dāng)有一個消息發(fā)出來,就會依次調(diào)用mS5,
mS1, mP1, mP0的processMessage方法(前提是都會返回false或者NOT_HANDLED)。

然后現(xiàn)在假設(shè)mS5的processMessage可以處理這個消息,并且會調(diào)用transitionTo(mS4)將狀態(tài)轉(zhuǎn)為mS4,然后返回true 或 HANDLED。processMessage返回后會進入performTransitions方法,其會找到mS5和mS4的共同父狀態(tài),也就是mP1。緊接著會依次調(diào)用mS5.exit, mS1.exit 然后是 mS2.enter mS4.enter. 這時mP0, mP1, mS2,mS4 這四個狀態(tài)是活動的,當(dāng)下一個消息到來的時候,就會激活mS4.processMessage方法。

下面是一個繼承了StateMachine的HelloWorld。該狀態(tài)機會在接收每一個消息的時候,打印一個 “Hello World” 字符串。

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 {&#64;Override public boolean processMessage(Message message) {Log.d(TAG, "Hello World");return HANDLED;}}State1 mState1 = new State1(); }void testHelloWorld() {HelloWorld hw = makeHelloWorld();hw.sendMessage(hw.obtainMessage()); }

下面是一個具有4個狀態(tài)的狀態(tài)機,并分為2個獨立的父狀態(tài)

mP1 mP2/ \mS2 mS1--初始狀態(tài)

下面是這幾個狀態(tài)的偽代碼

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;} }

測試代碼:

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");// 添加狀態(tài)addState(mP1);addState(mS1, mP1);addState(mS2, mP1);addState(mP2);// 設(shè)定初始狀態(tài)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_3sendMessage(obtainMessage(CMD_3));deferMessage(message);transitionTo(mS2);retVal = HANDLED;break;default:// Any message we don't understand in this state invokes unhandledMessageretVal = 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 calledtransitionTo(mS1);return HANDLED;} else {// Let parent process all other messagesreturn 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(); }

//注意:添加synchronize塊是因為我們使用了hsm.wait()。
Hsm1 hsm = makeHsm1();//創(chuàng)建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());
}
}
輸出:

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

畫一個流程圖

狀態(tài)機的實例–DataConnection

Android源碼中使用狀態(tài)機的地方不少,比如Wifi狀態(tài),數(shù)據(jù)連接狀態(tài),藍牙耳機狀態(tài)等,我們?nèi)”容^典型的Telephony中的DataConnection(Android4.2.2) 為例說明狀態(tài)機的使用。

其中DcDefaultState是所有狀態(tài)的父狀態(tài),

狀態(tài) 含義
DcInactiveState 非活動狀態(tài)
DcActivatingState 激活狀態(tài)
DcActiveState 活動狀態(tài)
DcDisconnectingState 去激活狀態(tài)
DcDisconnectionErrorCreatingConnection 創(chuàng)建連接時出錯狀態(tài)
狀態(tài)轉(zhuǎn)換圖

初始化

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

最開始處在DcInactiveState狀態(tài),當(dāng)DataConnectionTracker調(diào)用DataConnection的bringUp方法時

public void bringUp(Message onCompletedMsg, ApnSetting apn) {sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));}

會發(fā)送EVENT_CONNECT消息,這就會調(diào)用到當(dāng)前狀態(tài)DcInactiveState的processMessage方法。

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); //調(diào)用phone.mCM.setupDataCall 方法想RILJ發(fā)送RIL_REQUEST_SETUP_DATA_CALL請求。transitionTo(mActivatingState);//切換到mActivatingState狀態(tài)。retVal = HANDLED;break;} }

其他狀態(tài)的切換的處理根據(jù)需求和興趣自行閱讀即可。

總結(jié)

以上是生活随笔為你收集整理的Android中的设计模式-状态模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。