Handler和Looper的同步关系之HandlerThread

        为了引出HandlerThread类,我们现在先看看这样一个例子来说明Handler类和Looper类的同步关系:下面这段代码和例子出之《深入理解Android卷I》。

         前面不是说到过,使用Handler来处理消息有助与分担主线程的工作,将与UI主线程无关且耗时的工作放到单独的工作线程中去,那么我们看看下面这样一个需求假设线程1是UI主线程,线程2是工作线程

         

class LooperThread extends Thread{
      public Looper myLooper = null;
      public void run(){//假设run在线程2中执行
           Looper.perpare();
           //myLooper必须在这个线程中赋值
           myLooper = Looper.myLooper();
           Looper.loope();
   }
}

//下面这段代码在线程1中执行,并且会创建线程2
{
      LooperThread lpThread=new LooperThread;
      lpThread.start();//start后会创建线程2
      Looper looper = lpThread.myLooper;//-----注意-----
      //thread2Handler和线程2的Looper挂上钩
      Handler thread2Handler = new Handler(looper);
      //发送消息将有线程2来处理
      thread2Handler.sendMessage(。。。)
} 
        上面这段代码的目的在于,在线程一中创建线程2,并且线程1中得到线程2中创建的Looper对象,并且用这个线程2中创建的Looper对象来实例化一个Handler类 thread2Handler,那么通过这个 thread2Handler发送出去的消息都会在线程2中得到处理。
         上面这段的代码的问题在与,在线程1中给looper复制的时候线程2中的myLooper变量实例化完,这会导致在线程1中looper为null。

         在看看下面这两行代码的差别:      

      Handler thread2Handler = new Handler(looper) //不能替换成
      Handler thread2Handler = new Handler(Looper.myLooper())
      
          因为Looper.myLooper()函数返回的是当前线程(调用线程)的Looper,即如果使用第二种写法,那么不能像我们想的那样将线程2的looper传递给线程1。

          为了解决上面的问题,我们引入了HandlerThread类。

          下面我看看HandlerThread的内部接口

          

public class HandlerThread extends Thread {
    private int mPriority;
    private int mTid = -1;
    private Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    ...
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason is isAlive() returns false, this method will return null. If this thread 
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }


/*下面的代码来之WifiService.java*/
        HandlerThread wifiThread = new HandlerThread("WifiService");
        wifiThread.start();
        mWifiHandler = new WifiHandler(wifiThread.getLooper()); 

           假设在线程1中通过wifiThread.start()来开启线程2,线程1希望把对消息的处理函数放到线程2中去,在线程2开启的时候会运行run()函数,假设此时线程1从新获得CPU继续执行,进入到函数wifiThread.getLooper()中。那么如何保证线程1和线程2在Looper变量的传递上保持同步呢?HandlerThread中使用了一个java中的wait/notify机制,不懂的同学可以google下。在run()中如果mLooper变量实例化完成过后会notify来通知要取mLooper的线程1,同样在线程1中,如果getLooper()时还没有得到mLooper,则wait()等待唤醒。

        


           其实Android中光一个Looper Handler就够我们学的了,只是菜鸟不才,目前只能把自己大概知道的记录在这里,Ok诸位晚安,如果哪位大牛发现这篇blog有什么错误,敬请指教,免得误导了其他菜鸟....

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值