天天看點

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

<code>package</code>

<code>com.zte.liu.statemachine;</code>

<code>public</code>

<code>class</code> <code>hierarchicalstate {</code>

<code> </code> 

<code> </code><code>public</code>

<code>void</code> <code>enter(){</code>

<code>  </code> 

<code> </code><code>}</code>

<code>void</code> <code>exit(){</code>

<code>void</code> <code>processmessage(){</code>

<code>}</code>

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

<code>import</code>

<code>com.zte.liu.messagehandler.handlerthread;</code>

<code>com.zte.liu.messagehandler.looper;</code>

<code>com.zte.liu.messagehandler.message;</code>

<code>class</code> <code>hierarchicalstatemachine {</code>

<code> </code><code>private</code>

<code>hsmhandler mhandler;</code>

<code>handlerthread mhandlerthread;</code>

<code>defaultstate defaultstate =</code><code>new</code>

<code>defaultstate();</code>

<code>inactivestate inactivestate =</code><code>new</code>

<code>inactivestate();</code>

<code>activingstate activingstate =</code><code>new</code>

<code>activingstate();</code>

<code>activestate activestate =</code><code>new</code>

<code>activestate();</code>

<code>haltingstate haltingstate =</code><code>new</code>

<code>haltingstate();</code>

<code>quitingstate quitingstate =</code><code>new</code>

<code>quitingstate();</code>

<code>hierarchicalstatemachine(){</code>

<code>  </code><code>mhandlerthread =</code><code>new</code>

<code>handlerthread();</code>

<code>  </code><code>mhandlerthread.start();</code>

<code>  </code><code>looper looper = mhandlerthread.getlooper();</code>

<code>  </code><code>mhandler =</code><code>new</code>

<code>hsmhandler(looper);</code>

<code>class</code> <code>defaultstate</code><code>extends</code>

<code>hierarchicalstate{</code>

<code>class</code> <code>inactivestate</code><code>extends</code>

<code>class</code> <code>activingstate</code><code>extends</code>

<code>class</code> <code>activestate</code><code>extends</code>

<code>class</code> <code>haltingstate</code><code>extends</code>

<code>class</code> <code>quitingstate</code><code>extends</code>

<code>void</code> <code>addstate(hierarchicalstate state){</code>

<code>  </code><code>mhandler.addstate(state,</code><code>null</code><code>);</code>

<code>void</code> <code>addstate(hierarchicalstate state, hierarchicalstate parent){</code>

<code>  </code><code>mhandler.addstate(state, parent);</code>

<code>void</code> <code>setinitialstate(hierarchicalstate state){</code>

<code>  </code><code>mhandler.setinitialstate(state);</code>

<code>void</code> <code>start(){</code>

<code>  </code><code>mhandler.completeconstruction();</code>

<code>message obtainmessage(</code><code>int</code>

<code>what, object obj){</code>

<code>  </code><code>return</code>

<code>mhandler.obtainmessage(what, obj);</code>

<code>void</code> <code>sendmessage(message msg){</code>

<code>  </code><code>if</code><code>(msg !=</code><code>null</code><code>){</code>

<code>   </code><code>msg.sendtotarget();</code>

<code>  </code><code>}</code>

<code>void</code> <code>defermessage(message msg){</code>

<code>  </code><code>mhandler.defermessage(msg);</code>

<code>void</code> <code>transitionto(hierarchicalstate deststate){</code>

<code>  </code><code>mhandler.transitionto(deststate);</code>

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

<code>java.util.arraylist;</code>

<code>java.util.hashmap;</code>

<code>com.zte.liu.messagehandler.handler;</code>

<code>com.zte.liu.messagehandler.messagequeue;</code>

<code>class</code> <code>hsmhandler</code><code>extends</code>

<code>handler {</code>

<code>hashmap&lt;hierarchicalstate, stateinfo&gt; mstateinfo =</code><code>new</code>

<code>hashmap&lt;hierarchicalstate, stateinfo&gt;();</code>

<code>hierarchicalstate minitialstate =</code><code>null</code><code>;</code>

<code>hierarchicalstate mdeststate =</code><code>null</code><code>;</code>

<code>arraylist&lt;stateinfo&gt; minitialstatelist =</code><code>new</code>

<code>arraylist&lt;stateinfo&gt;();</code>

<code>arraylist&lt;message&gt; mdeferredmessages =</code><code>new</code>

<code>arraylist&lt;message&gt;();</code>

<code>hsmhandler(looper looper) {</code>

<code>  </code><code>super</code><code>(looper);</code>

<code>class</code> <code>stateinfo{</code>

<code>  </code><code>hierarchicalstate state;</code>

<code>  </code><code>hierarchicalstate parentstate;</code>

<code>  </code><code>boolean</code>

<code>active;</code>

<code>void</code> <code>addstate(hierarchicalstate state, hierarchicalstate parentstate){</code><code>//隻在非多線程情況</code>

<code>  </code><code>if</code><code>(state ==</code><code>null</code><code>){</code>

<code>   </code><code>throw</code>

<code>new</code> <code>runtimeexception(</code><code>"state cannot be null when adding state."</code><code>);</code>

<code>/*  if(mstateinfo.containskey(state) &amp;&amp; mstateinfo.get(state).parentstate!=parentstate){</code>

<code>   </code><code>throw new runtimeexception("we cannot add a state with different parents.");</code>

<code>*/</code>

<code>  </code><code>if</code><code>(mstateinfo.containskey(state)){</code>

<code>   </code><code>return</code><code>;</code>

<code>  </code><code>stateinfo stateinfo =</code><code>new</code>

<code>stateinfo();</code>

<code>  </code><code>stateinfo.state = state;</code>

<code>  </code><code>stateinfo.parentstate = parentstate;</code>

<code>  </code><code>stateinfo.active =</code><code>false</code><code>;</code>

<code>  </code><code>mstateinfo.put(state, stateinfo);</code>

<code>  </code><code>if</code><code>(!mstateinfo.containskey(state)){</code>

<code>new</code> <code>runtimeexception(</code><code>"cannot set a initial state which is not contained in the build tree."</code><code>);</code>

<code>  </code><code>minitialstate = state;</code>

<code>void</code> <code>completeconstruction(){</code>

<code>  </code><code>if</code><code>(minitialstate ==</code><code>null</code><code>){</code>

<code>  </code><code>stateinfo initialstateinfo = mstateinfo.get(minitialstate);</code>

<code>  </code><code>while</code><code>(initialstateinfo !=</code><code>null</code><code>){</code>

<code>   </code><code>minitialstatelist.add(initialstateinfo);</code>

<code>   </code><code>if</code><code>(initialstateinfo.parentstate ==</code><code>null</code><code>){</code>

<code>    </code><code>initialstateinfo =</code><code>null</code><code>;</code>

<code>   </code><code>}</code><code>else</code><code>{</code>

<code>    </code><code>initialstateinfo = mstateinfo.get(initialstateinfo.parentstate);</code>

<code>   </code><code>}</code>

<code>  </code><code>invokeentermethods(</code><code>null</code><code>);</code>

<code>  </code><code>performtransitions();</code>

<code>void</code> <code>invokeentermethods(stateinfo commonstateinfo){</code>

<code>  </code><code>int</code>

<code>start = minitialstatelist.size() -</code><code>1</code><code>;</code>

<code>  </code><code>for</code><code>(</code><code>int</code>

<code>i=minitialstatelist.size()-</code><code>1</code><code>; i&gt;=</code><code>0</code><code>; i--){</code>

<code>   </code><code>if</code><code>(minitialstatelist.get(i) == commonstateinfo){</code>

<code>    </code><code>start = i -</code><code>1</code><code>;</code>

<code>    </code><code>break</code><code>;</code>

<code>i=start; i&gt;=</code><code>0</code><code>; i--){</code>

<code>   </code><code>stateinfo stateinfo = minitialstatelist.get(i);</code>

<code>   </code><code>stateinfo.state.enter();</code>

<code>   </code><code>stateinfo.active =</code><code>true</code><code>;</code>

<code>void</code> <code>invokeexitmethods(stateinfo commonstateinfo){</code>

<code>i=</code><code>0</code><code>; i&lt;minitialstatelist.size()-</code><code>1</code><code>; i++){</code>

<code>   </code><code>stateinfo stateinfo = (stateinfo)minitialstatelist.get(i);</code>

<code>   </code><code>if</code><code>(stateinfo != commonstateinfo){</code>

<code>    </code><code>stateinfo.state.exit();</code>

<code>    </code><code>stateinfo.active =</code><code>false</code><code>;</code>

<code>void</code> <code>performtransitions(){</code>

<code>  </code><code>if</code><code>(mdeststate ==</code><code>null</code><code>){</code>

<code>  </code><code>arraylist&lt;stateinfo&gt; templist =</code><code>new</code>

<code>  </code><code>stateinfo commonstateinfo = getcommonstateinfo(mdeststate, templist);</code>

<code>  </code><code>invokeexitmethods(commonstateinfo);</code>

<code>  </code><code>refreshinitialstatelist(commonstateinfo, templist);</code>

<code>  </code><code>invokeentermethods(commonstateinfo);</code>

<code>  </code><code>movedeferredmsgatfrontqueue();</code>

<code>  </code><code>mdeferredmessages.add(msg);</code>

<code>void</code> <code>handlemessage(message msg){</code><code>//重寫!!</code>

<code>  </code><code>///////////////////////////////////////</code>

<code>  </code><code>//////////////////////////////////////</code>

<code>  </code><code>mdeststate = deststate;</code>

<code>stateinfo getcommonstateinfo(hierarchicalstate deststate, arraylist&lt;stateinfo&gt; templist){</code>

<code>  </code><code>stateinfo stateinfo = mstateinfo.get(deststate);</code>

<code>  </code><code>while</code><code>(stateinfo!=</code><code>null</code>

<code>&amp;&amp; stateinfo.active==</code><code>false</code><code>){</code>

<code>   </code><code>templist.add(stateinfo);</code>

<code>   </code><code>if</code><code>(stateinfo.parentstate ==</code><code>null</code><code>){</code>

<code>    </code><code>stateinfo =</code><code>null</code><code>;</code>

<code>    </code><code>stateinfo = mstateinfo.get(stateinfo.parentstate);</code>

<code>stateinfo;</code>

<code>void</code> <code>refreshinitialstatelist(stateinfo commonstateinfo, arraylist&lt;stateinfo&gt; templist){</code>

<code>   </code><code>if</code><code>(minitialstatelist.get(i) != commonstateinfo){</code>

<code>    </code><code>minitialstatelist.remove(i);</code>

<code>i=templist.size()-</code><code>1</code><code>; i&gt;=</code><code>0</code><code>; i--){</code>

<code>   </code><code>minitialstatelist.add(</code><code>0</code><code>, templist.get(i));</code>

<code>void</code> <code>movedeferredmsgatfrontqueue(){</code>

<code>  </code><code>messagequeue msgqueue =</code><code>this</code><code>.getlooper().getqueue();</code>

<code>i=mdeferredmessages.size()-</code><code>1</code><code>; i&gt;=</code><code>0</code><code>; i--){</code>

<code>   </code><code>msgqueue.addtofront(mdeferredmessages.get(i));</code>

繼續閱讀