前面说过消息注册机制是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>