閱讀360 返回首頁    go 技術社區[雲棲]


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

  上一篇:go 判斷eclipse版本能否支持java 1.7的方法
  下一篇:go VS2010中使用JSONCPP方法