上一篇文章提到了Android系统的UI线程是一种带消息循环(Looper)机制的线程,同时Android也提供了封装有消息循环(Looper)的HandlerThread类,这种线程,可以绑定Handler()对象,并通过Handler的sendMessage()函数向线程发送消息,通过handleMessage()函数,处理线程接收到的消息。这么说比较抽象,那么,本文就利用基础的Java类库,实现一个带消息循环(Looper)的线程,以帮助初学者理解这样一个Looper到底是怎么工作的。
创新互联于2013年成立,先为安新等服务建站,安新等地企业,进行企业商务咨询服务。为安新企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。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 QueuemMessageQueue = new LinkedList (); 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交流,或者关注我的新浪微博 @卢_俊 获取最新的文章和资讯。
附件:http://down.51cto.com/data/2364962另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。