【转】Android开发实践:自定义带消息循环(Looper)的工作线程

 http://ticktick.blog.51cto.com/823160/1565272

上一篇文章提到了Android系统的UI线程是一种带消息循环(Looper)机制的线程,同时Android也提供了封装有消息循环(Looper)的HandlerThread类,这种线程,可以绑定Handler()对象,并通过Handler的sendMessage()函数向线程发送消息,通过handleMessage()函数,处理线程接收到的消息。这么说比较抽象,那么,本文就利用基础的Java类库,实现一个带消息循环(Looper)的线程,以帮助初学者理解这样一个Looper到底是怎么工作的。

1. 首先,我们完成一个简单的线程框架。

public class LooperThread {
  
  private volatile boolean mIsLooperQuit = false;
    
  private Thread mThread;	  
  
  public void start() {		
    if( mThread != null ) {
      return;
    }		
    mIsLooperQuit = false;
    mThread = new Thread(mLooperRunnable);
    mThread.start();		
  }
  
  public void stop() {		
    if( mThread == null ) {
      return;
    }		
    mIsLooperQuit = true;
    mThread = null;	
  }

  protected Runnable mLooperRunnable = new Runnable() {		

    @Override
    public void run() {
      while( !mIsLooperQuit ) {
      
      }
    }
  };		
}

如上述代码所示,mLooperRunnable.run()循环执行线程任务,mIsLooperQuit则是线程退出循环的条件。下面,我们将添加消息的发送和处理代码。

2. 添加线程循环的消息发送和处理代码

(1) 定义消息结构体,创建消息队列

public class LooperThread {

    private Queue<Message> mMessageQueue = new LinkedList<Message>();
    
    public static class Message {
    	int what;
    }        
}

 

(2) 创建互斥锁和条件变量

 

public class LooperThread {

     private Lock mLock = new ReentrantLock();
     private Condition mCondition = mLock.newCondition();       
}

(3) 创建发送消息的函数

//发送消息,由外部其他模块调用,发送消息给线程
public void sendMessage( Message message ) {
  if( mThread == null ) {
    return;
  }		
  mLock.lock();
  mMessageQueue.add(message); //添加消息到消息队列
  mCondition.signal();		//通知线程循环,有消息来了,请立即处理
  mLock.unlock();
}

(4) 创建处理消息的函数

//处理消息,由线程内部调用
public void handleMessage(Message message) {
    //这里可以通过一个Callback来回调监听者
}

(5) 在mLooperRunnable.run()循环中解析消息

protected Runnable mLooperRunnable = new Runnable() {		
    
  @Override
  public void run() {
    
    while( !mIsLooperQuit ) {
    
      mLock.lock();
      Message message = null;
    
      try {
        while( !mIsLooperQuit && mMessageQueue.isEmpty() ) {
          mCondition.await(); //没有消息到来则休眠
        } 
        message = mMessageQueue.poll();					
      }
      catch (InterruptedException e) {
        e.printStackTrace();			
      }
      finally {
        mLock.unlock();
      }		
      
      handleMessage(message );
    }					
  };		
}

(6) 修改线程的Stop()函数,唤醒休眠的消息循环

public void stop() {		

  if( mThread == null ) {
    return;
  }		

  mIsLooperQuit = true;	
    
  mLock.lock();		
  mCondition.signal();
  mLock.unlock();
  
  mMessageQueue.clear();
  mThread = null;		
}

到这里,一个基本的带有消息循环的线程类封装就完成了,相信大家应该从编写这段代码的过程中,理解了系统是如何实现消息循环的。完整的代码见博文最后的附件,有任何疑问欢迎留言或者来信lujun.hust@gmail.com交流。

posted @ 2016-05-16 17:29  牧之丨  阅读(1140)  评论(0编辑  收藏  举报