Android也提供了封装有消息循环(Looper)的HandlerThread类,这种线程,可以绑定Handler()对象,并通过 Handler的sendMessage()函数向线程发送消息,通过handleMessage()函数,处理线程接收到的消息。这么说比较抽象,那 么,本文就利用基础的Java类库,实现一个带消息循环(Looper)的线程,以帮助初学者理解这样一个Looper到底是怎么工作的。
1. 首先,我们完成一个简单的线程框架。
1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
<div class="line number18 index17 alt1">
18
</div>
<div class="line number19 index18 alt2">
19
</div>
<div class="line number20 index19 alt1">
20
</div>
<div class="line number21 index20 alt2">
21
</div>
<div class="line number22 index21 alt1">
22
</div>
<div class="line number23 index22 alt2">
23
</div>
<div class="line number24 index23 alt1">
24
</div>
<div class="line number25 index24 alt2">
25
</div>
<div class="line number26 index25 alt1">
26
</div>
<div class="line number27 index26 alt2">
27
</div>
<div class="line number28 index27 alt1">
28
</div>
<div class="line number29 index28 alt2">
29
</div>
<div class="line number30 index29 alt1">
30
</div>
<div class="line number31 index30 alt2">
31
</div>
<div class="line number32 index31 alt1">
32
</div>
<div class="line number33 index32 alt2">
33
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`public` `class` `LooperThread {`
</div>
<div class="line number2 index1 alt1">
` `
</div>
<div class="line number3 index2 alt2">
` ``private` `volatile` `boolean` `mIsLooperQuit = ``false``;`
</div>
<div class="line number4 index3 alt1">
` `
</div>
<div class="line number5 index4 alt2">
` ``private` `Thread mThread; `
</div>
<div class="line number6 index5 alt1">
` `
</div>
<div class="line number7 index6 alt2">
` ``public` `void` `start() { `
</div>
<div class="line number8 index7 alt1">
` ``if``( mThread != ``null` `) {`
</div>
<div class="line number9 index8 alt2">
` ``return``;`
</div>
<div class="line number10 index9 alt1">
` ``} `
</div>
<div class="line number11 index10 alt2">
` ``mIsLooperQuit = ``false``;`
</div>
<div class="line number12 index11 alt1">
` ``mThread = ``new` `Thread(mLooperRunnable);`
</div>
<div class="line number13 index12 alt2">
` ``mThread.start(); `
</div>
<div class="line number14 index13 alt1">
` ``}`
</div>
<div class="line number15 index14 alt2">
` `
</div>
<div class="line number16 index15 alt1">
` ``public` `void` `stop() { `
</div>
<div class="line number17 index16 alt2">
` ``if``( mThread == ``null` `) {`
</div>
<div class="line number18 index17 alt1">
` ``return``;`
</div>
<div class="line number19 index18 alt2">
` ``} `
</div>
<div class="line number20 index19 alt1">
` ``mIsLooperQuit = ``true``;`
</div>
<div class="line number21 index20 alt2">
` ``mThread = ``null``; `
</div>
<div class="line number22 index21 alt1">
` ``}`
</div>
<div class="line number23 index22 alt2">
</div>
<div class="line number24 index23 alt1">
` ``protected` `Runnable mLooperRunnable = ``new` `Runnable() { `
</div>
<div class="line number25 index24 alt2">
</div>
<div class="line number26 index25 alt1">
` ``@Override`
</div>
<div class="line number27 index26 alt2">
` ``public` `void` `run() {`
</div>
<div class="line number28 index27 alt1">
` ``while``( !mIsLooperQuit ) {`
</div>
<div class="line number29 index28 alt2">
` `
</div>
<div class="line number30 index29 alt1">
` ``}`
</div>
<div class="line number31 index30 alt2">
` ``}`
</div>
<div class="line number32 index31 alt1">
` ``}; `
</div>
<div class="line number33 index32 alt2">
`}`
</div>
</div>
</td>
</tr>
</table>
如上述代码所示,mLooperRunnable.run()循环执行线程任务,mIsLooperQuit则是线程退出循环的条件。下面,我们将添加消息的发送和处理代码。 2. 添加线程循环的消息发送和处理代码 ** ** (1) 定义消息结构体,创建消息队列 ** ** 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`public` `class` `LooperThread {`
</div>
<div class="line number2 index1 alt1">
</div>
<div class="line number3 index2 alt2">
` ``private` `Queue<Message> mMessageQueue = ``new` `LinkedList<Message>();`
</div>
<div class="line number4 index3 alt1">
` `
</div>
<div class="line number5 index4 alt2">
` ``public` `static` `class` `Message {`
</div>
<div class="line number6 index5 alt1">
` ``int` `what;`
</div>
<div class="line number7 index6 alt2">
` ``} `
</div>
<div class="line number8 index7 alt1">
`}`
</div>
</div>
</td>
</tr>
</table>
**(2) 创建互斥锁和条件变量 ** ** ** 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`public` `class` `LooperThread {`
</div>
<div class="line number2 index1 alt1">
</div>
<div class="line number3 index2 alt2">
` ``private` `Lock mLock = ``new` `ReentrantLock();`
</div>
<div class="line number4 index3 alt1">
` ``private` `Condition mCondition = mLock.newCondition(); `
</div>
<div class="line number5 index4 alt2">
`}`
</div>
</div>
</td>
</tr>
</table>
(3) 创建发送消息的函数 ** ** 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`//发送消息,由外部其他模块调用,发送消息给线程`
</div>
<div class="line number2 index1 alt1">
`public` `void` `sendMessage( Message message ) {`
</div>
<div class="line number3 index2 alt2">
` ``if``( mThread == ``null` `) {`
</div>
<div class="line number4 index3 alt1">
` ``return``;`
</div>
<div class="line number5 index4 alt2">
` ``} `
</div>
<div class="line number6 index5 alt1">
` ``mLock.lock();`
</div>
<div class="line number7 index6 alt2">
` ``mMessageQueue.add(message); ``//添加消息到消息队列`
</div>
<div class="line number8 index7 alt1">
` ``mCondition.signal(); ``//通知线程循环,有消息来了,请立即处理`
</div>
<div class="line number9 index8 alt2">
` ``mLock.unlock();`
</div>
<div class="line number10 index9 alt1">
`}`
</div>
</div>
</td>
</tr>
</table>
(4) 创建处理消息的函数 ** ** 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`//处理消息,由线程内部调用`
</div>
<div class="line number2 index1 alt1">
`public` `void` `handleMessage(Message message) {`
</div>
<div class="line number3 index2 alt2">
` ``//这里可以通过一个Callback来回调监听者`
</div>
<div class="line number4 index3 alt1">
`}`
</div>
</div>
</td>
</tr>
</table>
(5) 在mLooperRunnable.run()循环中解析消息 ** ** 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
<div class="line number18 index17 alt1">
18
</div>
<div class="line number19 index18 alt2">
19
</div>
<div class="line number20 index19 alt1">
20
</div>
<div class="line number21 index20 alt2">
21
</div>
<div class="line number22 index21 alt1">
22
</div>
<div class="line number23 index22 alt2">
23
</div>
<div class="line number24 index23 alt1">
24
</div>
<div class="line number25 index24 alt2">
25
</div>
<div class="line number26 index25 alt1">
26
</div>
<div class="line number27 index26 alt2">
27
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`protected` `Runnable mLooperRunnable = ``new` `Runnable() { `
</div>
<div class="line number2 index1 alt1">
` `
</div>
<div class="line number3 index2 alt2">
` ``@Override`
</div>
<div class="line number4 index3 alt1">
` ``public` `void` `run() {`
</div>
<div class="line number5 index4 alt2">
` `
</div>
<div class="line number6 index5 alt1">
` ``while``( !mIsLooperQuit ) {`
</div>
<div class="line number7 index6 alt2">
` `
</div>
<div class="line number8 index7 alt1">
` ``mLock.lock();`
</div>
<div class="line number9 index8 alt2">
` ``Message message = ``null``;`
</div>
<div class="line number10 index9 alt1">
` `
</div>
<div class="line number11 index10 alt2">
` ``try` `{`
</div>
<div class="line number12 index11 alt1">
` ``while``( !mIsLooperQuit && mMessageQueue.isEmpty() ) {`
</div>
<div class="line number13 index12 alt2">
` ``mCondition.await(); ``//没有消息到来则休眠`
</div>
<div class="line number14 index13 alt1">
` ``} `
</div>
<div class="line number15 index14 alt2">
` ``message = mMessageQueue.poll(); `
</div>
<div class="line number16 index15 alt1">
` ``}`
</div>
<div class="line number17 index16 alt2">
` ``catch` `(InterruptedException e) {`
</div>
<div class="line number18 index17 alt1">
` ``e.printStackTrace(); `
</div>
<div class="line number19 index18 alt2">
` ``}`
</div>
<div class="line number20 index19 alt1">
` ``finally` `{`
</div>
<div class="line number21 index20 alt2">
` ``mLock.unlock();`
</div>
<div class="line number22 index21 alt1">
` ``} `
</div>
<div class="line number23 index22 alt2">
` `
</div>
<div class="line number24 index23 alt1">
` ``handleMessage(message );`
</div>
<div class="line number25 index24 alt2">
` ``} `
</div>
<div class="line number26 index25 alt1">
` ``}; `
</div>
<div class="line number27 index26 alt2">
`}`
</div>
</div>
</td>
</tr>
</table>
(6) 修改线程的Stop()函数,唤醒休眠的消息循环 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`public` `void` `stop() { `
</div>
<div class="line number2 index1 alt1">
</div>
<div class="line number3 index2 alt2">
` ``if``( mThread == ``null` `) {`
</div>
<div class="line number4 index3 alt1">
` ``return``;`
</div>
<div class="line number5 index4 alt2">
` ``} `
</div>
<div class="line number6 index5 alt1">
</div>
<div class="line number7 index6 alt2">
` ``mIsLooperQuit = ``true``; `
</div>
<div class="line number8 index7 alt1">
` `
</div>
<div class="line number9 index8 alt2">
` ``mLock.lock(); `
</div>
<div class="line number10 index9 alt1">
` ``mCondition.signal();`
</div>
<div class="line number11 index10 alt2">
` ``mLock.unlock();`
</div>
<div class="line number12 index11 alt1">
` `
</div>
<div class="line number13 index12 alt2">
` ``mMessageQueue.clear();`
</div>
<div class="line number14 index13 alt1">
` ``mThread = ``null``; `
</div>
<div class="line number15 index14 alt2">
`}`
</div>
</div>
</td>
</tr>
</table>
到这里,一个基本的带有消息循环的线程类封装就完成了,相信大家应该从编写这段代码的过程中,理解了系统是如何实现消息循环的 附近: LooperThread 转自:http://ticktick.blog.51cto.com/823160/1565272
|
|
|
|
|
|
|
💬 评论