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&lt;Message&gt; mMessageQueue = ``new` `LinkedList&lt;Message&gt;();`
        </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

 

💬 评论