zoukankan      html  css  js  c++  java
  • 【转】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交流。

  • 相关阅读:
    JVM相关知识
    面试之mysql专题
    Java新特性
    数据结构操作与算法复杂度分析
    IO流
    浅谈Web安全
    面试题2
    需要知道的HTTP 知识
    How JavaScript Work
    webpack 学习笔记
  • 原文地址:https://www.cnblogs.com/exmyth/p/5498854.html
Copyright © 2011-2022 走看看