前面說過消息注冊機制是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<hierarchicalstate, stateinfo> mstateinfo =</code><code>new</code>
<code>hashmap<hierarchicalstate, stateinfo>();</code>
<code>hierarchicalstate minitialstate =</code><code>null</code><code>;</code>
<code>hierarchicalstate mdeststate =</code><code>null</code><code>;</code>
<code>arraylist<stateinfo> minitialstatelist =</code><code>new</code>
<code>arraylist<stateinfo>();</code>
<code>arraylist<message> mdeferredmessages =</code><code>new</code>
<code>arraylist<message>();</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) && 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>=</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>=</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<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<stateinfo> 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<stateinfo> templist){</code>
<code> </code><code>stateinfo stateinfo = mstateinfo.get(deststate);</code>
<code> </code><code>while</code><code>(stateinfo!=</code><code>null</code>
<code>&& 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<stateinfo> 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>=</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>=</code><code>0</code><code>; i--){</code>
<code> </code><code>msgqueue.addtofront(mdeferredmessages.get(i));</code>