360
技術社區[雲棲]
Android中的狀態機 機製
前麵說過消息注冊機製是MessageHandler的一個應用,它的好處就是能在程序中自如地控製消息注冊和消息發送兩個步驟。但是很多情況下,問題的解決是在很多個環節完成的,每個環節理解成特定的狀態,在每個狀態下都會有新消息的發送或者新狀態的切換。那麼設計就需要考慮如何將Message的處理操作放到指定的狀態機中,這是程序設計的關鍵。
總體思想:
(1)先初始化狀態機,設置初始狀態。
(2)內存中加載handler對象,要知道所有Message的處理都的經過它,所以在複寫handleMessage的時候需要將當前Message分發到當前最新狀態。
下麵是模擬程序,剛寫的,沒調試,而且不全麵,隻寫了骨架,但更直觀便於閱讀。明天調試看看,得出完整版本的,最好結合PDP建立過程講解PDP建立的狀態機過程。
這裏列舉3個類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package
com.zte.liu.statemachine;
public
class
HierarchicalState {
public
void
enter(){
}
public
void
exit(){
}
public
void
processMessage(){
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
package
com.zte.liu.statemachine;
import
com.zte.liu.messagehandler.HandlerThread;
import
com.zte.liu.messagehandler.Looper;
import
com.zte.liu.messagehandler.Message;
public
class
HierarchicalStateMachine {
private
HsmHandler mHandler;
private
HandlerThread mHandlerThread;
private
DefaultState defaultState = new
DefaultState();
private
InactiveState inActiveState = new
InactiveState();
private
ActivingState activingState = new
ActivingState();
private
ActiveState activeState = new
ActiveState();
private
HaltingState haltingState = new
HaltingState();
private
QuitingState quitingState = new
QuitingState();
public
HierarchicalStateMachine(){
mHandlerThread
= new
HandlerThread();
mHandlerThread.start();
Looper
looper = mHandlerThread.getLooper();
mHandler
= new
HsmHandler(looper);
}
private
class
DefaultState extends
HierarchicalState{
}
private
class
InactiveState extends
HierarchicalState{
}
private
class
ActivingState extends
HierarchicalState{
}
private
class
ActiveState extends
HierarchicalState{
}
private
class
HaltingState extends
HierarchicalState{
}
private
class
QuitingState extends
HierarchicalState{
}
public
void
addState(HierarchicalState state){
mHandler.addState(state,
null );
}
public
void
addState(HierarchicalState state, HierarchicalState parent){
mHandler.addState(state,
parent);
}
public
void
setInitialState(HierarchicalState state){
mHandler.setInitialState(state);
}
public
void
start(){
mHandler.completeConstruction();
}
public
Message obtainMessage( int
what, Object obj){
return
mHandler.obtainMessage(what, obj);
}
public
void
sendMessage(Message msg){
if (msg
!= null ){
msg.sendToTarget();
}
}
public
void
deferMessage(Message msg){
mHandler.deferMessage(msg);
}
public
void
transitionTo(HierarchicalState destState){
mHandler.transitionTo(destState);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
package
com.zte.liu.statemachine;
import
java.util.ArrayList;
import
java.util.HashMap;
import
com.zte.liu.messagehandler.Handler;
import
com.zte.liu.messagehandler.Looper;
import
com.zte.liu.messagehandler.Message;
import
com.zte.liu.messagehandler.MessageQueue;
public
class
HsmHandler extends
Handler {
private
HashMap<HierarchicalState, StateInfo> mStateInfo = new
HashMap<HierarchicalState, StateInfo>();
private
HierarchicalState mInitialState = null ;
private
HierarchicalState mDestState = null ;
private
ArrayList<StateInfo> mInitialStateList = new
ArrayList<StateInfo>();
private
ArrayList<Message> mDeferredMessages = new
ArrayList<Message>();
public
HsmHandler(Looper looper) {
super (looper);
}
private
class
StateInfo{
HierarchicalState
state;
HierarchicalState
parentState;
boolean
active;
}
public
void
addState(HierarchicalState state, HierarchicalState parentState){ //隻在非多線程情況
if (state
== null ){
throw
new
RuntimeException( "state
cannot be null when adding state." );
}
/*
if(mStateInfo.containsKey(state) && mStateInfo.get(state).parentState!=parentState){
throw
new RuntimeException("we cannot add a state with different parents.");
}
*/
if (mStateInfo.containsKey(state)){
return ;
}
StateInfo
stateInfo = new
StateInfo();
stateInfo.state
= state;
stateInfo.parentState
= parentState;
stateInfo.active
= false ;
mStateInfo.put(state,
stateInfo);
}
public
void
setInitialState(HierarchicalState state){
if (!mStateInfo.containsKey(state)){
throw
new
RuntimeException( "cannot
set a initial state which is not contained in the build tree." );
}
mInitialState
= state;
}
public
void
completeConstruction(){
if (mInitialState
== null ){
return ;
}
StateInfo
initialStateInfo = mStateInfo.get(mInitialState);
while (initialStateInfo
!= null ){
mInitialStateList.add(initialStateInfo);
if (initialStateInfo.parentState
== null ){
initialStateInfo
= null ;
} else {
initialStateInfo
= mStateInfo.get(initialStateInfo.parentState);
}
}
invokeEnterMethods( null );
performTransitions();
}
public
void
invokeEnterMethods(StateInfo commonStateInfo){
int
start = mInitialStateList.size() - 1 ;
for ( int
i=mInitialStateList.size()- 1 ;
i>= 0 ;
i--){
if (mInitialStateList.get(i)
== commonStateInfo){
start
= i - 1 ;
break ;
}
}
for ( int
i=start; i>= 0 ;
i--){
StateInfo
stateInfo = mInitialStateList.get(i);
stateInfo.state.enter();
stateInfo.active
= true ;
}
}
public
void
invokeExitMethods(StateInfo commonStateInfo){
for ( int
i= 0 ;
i<mInitialStateList.size()- 1 ;
i++){
StateInfo
stateInfo = (StateInfo)mInitialStateList.get(i);
if (stateInfo
!= commonStateInfo){
stateInfo.state.exit();
stateInfo.active
= false ;
} else {
break ;
}
}
}
public
void
performTransitions(){
if (mDestState
== null ){
return ;
}
ArrayList<StateInfo>
tempList = new
ArrayList<StateInfo>();
StateInfo
commonStateInfo = getCommonStateInfo(mDestState, tempList);
invokeExitMethods(commonStateInfo);
refreshInitialStateList(commonStateInfo,
tempList);
invokeEnterMethods(commonStateInfo);
moveDeferredMsgAtFrontQueue();
}
public
void
deferMessage(Message msg){
mDeferredMessages.add(msg);
}
public
void
handleMessage(Message msg){ //重寫!!
///////////////////////////////////////
//////////////////////////////////////
}
public
void
transitionTo(HierarchicalState destState){
mDestState
= destState;
}
private
StateInfo getCommonStateInfo(HierarchicalState destState, ArrayList<StateInfo> tempList){
StateInfo
stateInfo = mStateInfo.get(destState);
while (stateInfo!= null
&& stateInfo.active== false ){
tempList.add(stateInfo);
if (stateInfo.parentState
== null ){
stateInfo
= null ;
} else {
stateInfo
= mStateInfo.get(stateInfo.parentState);
}
}
return
stateInfo;
}
private
void
refreshInitialStateList(StateInfo commonStateInfo, ArrayList<StateInfo> tempList){
for ( int
i= 0 ;
i<mInitialStateList.size()- 1 ;
i++){
if (mInitialStateList.get(i)
!= commonStateInfo){
mInitialStateList.remove(i);
}
}
for ( int
i=tempList.size()- 1 ;
i>= 0 ;
i--){
mInitialStateList.add( 0 ,
tempList.get(i));
}
}
private
void
moveDeferredMsgAtFrontQueue(){
MessageQueue
msgQueue = this .getLooper().getQueue();
for ( int
i=mDeferredMessages.size()- 1 ;
i>= 0 ;
i--){
msgQueue.addToFront(mDeferredMessages.get(i));
}
}
}
|
最後更新:2017-04-02 06:52:03