HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,它有个Looper成员变量。这个Looper其实就是对消息队列以及队列处理逻辑的封装,简单说就是 消息队列+消息循环。


当我们需要一个工作者线程,而不是把它当作一次性消耗品,用过即废弃的话,就可以使用它。

private Handler mHandler = null;

     private HandlerThread mHandlerThread = null;    private void sentRunnableToWorker(Runnable run){
        if (null == mHandlerThread)
         {
             mHandlerThread = new HandlerThread("WorkerThread");            // 给工作者线程低优先级 
             mHandlerThread.setPriority(Thread.MIN_PRIORITY);
             mHandlerThread.start();
         }

         if (null == mHandler)
             mHandler = new Handler(mHandlerThread.getLooper());

         mHandler.post(run);    }

AsyncQueryHandler就是基于HandlerThread封装了线程间双向通信,而HandlerThread只做了一半。

 

 

源码分析:

 



1. public class HandlerThread extends Thread{ 
2.           //线程的优先级 
3.            private int mPriority; 
4.           //线程的id 
5.            private int mTid=-1; 
6.            private Looper mLooper; 
7.            public HandlerThread(String name){ 
8.                       super(name); 
9.                      //设置优先级为默认线程 
10.                      mPriority=Process.THREAD_PRIORITY_DEFAULT; 
11.            } 
12.            public HandlerThread(String name,int priority){ 
13.                       super(name); 
14.                      mPriority=priority; 
15.            } 
16.           //这个如果有需要的话可以继承重写,例如可以在里面声明个Handler 关联此线程。 
17.            protected void onLooperPrepared(){} 
18.            //这个很熟悉吧 
19.            public void run(){ 
20.                //得到当前线程的id 
21.                 mTid=Process.myTid; 
22.                //一旦调用这句代码,就在此线程中创建了Looper 对象。这就是为什么我们要在调用线程的start()方法后 
23.                //才能得到Looper 对象即 当 调用Looper.myLooper()时不为Null。 
24.                 Looper.prepare(); 
25.                 //同步代码块,意思就是当获得mLooper对象后,唤醒所有线程。(会在以后的例子中有所体现) 
26.                synchronized(this){ 
27.                      mLooper=Looper.myLooper(); 
28.                      notifyAll(); 
29.                } 
30.               //设置线程的优先级 
31.                Process.setThreadPriority(mPriority); 
32.              //调用上面的方法(需要用户重写) 
33.               onLooperPrepared(); 
34.                //建立了消息循环 
35.                 Looper.loop(); 
36.                mTid=-1; 
37.            } 
38.            public Looper getLooper(){ 
39.                     //线程死了,那就只有NULL了。 
40.                      if(!isAlive()){ 
41.                         return null; 
42.                     } 
43.             //看见没,又是同步代码块,正好和上面的形成对应,就是说只要线程活着并且我的looper为NULL,那么我就让你一直等。。。 
44.                    synchronized(this){ 
45.                           while(isAlive()&&mLooper==null){ 
46.                                try{ 
47.                                          wait(); 
48.                                    }catch(InterruptedException e){} 
49.                           } 
50.                    } 
51.                              return mLooper; 
52.            } 
53.           public boolean quit(){ 
54.               Looper looper =getLooper(); 
55.                if(looper!=null){ 
56.                   //退出消息循环 
57.                    looper.quit(); 
58.                    return true; 
59.               } 
60.               return false; 
61.        } 
62.          //返回线程ID 
63.          public int getThreadId(){ 
64.                return mTid; 
65.         } 
66. }


复制代码



整体来说代码还是比较浅显易懂的。主要的作用是建立了一个线程,并且创立了消息队列,有来自己的looper,可以让我们在自己的线程中分发和处理消息。具体的使用示例,我会在下一帖中体现。还有要说明的是handler 与谁相关联不是看声明在什么地方,是看与哪个线程的looper挂钩。默认是主线程的looper.因为主线程中默认就有了looper,消息循环队列。


 


每天进步一点点之AsyncQueryHandler学习

AsyncQueryHandler:异步的查询操作帮助类,其实它同样可以处理增删改

1。AsyncQueryHandler的作用

查询其API便可知,它担供:

startInsert

startDelete

startUpdate

startQuery

onXXXComplete方法,以供操作完数据库后进行其它的操作,这四个onXXXComplete方法都是空实现,以便我们只需要去实现我们关注的操作。

 

2。为什么要使用AsyncQueryHandler

当然你也可以使用ContentProvider去操作数据库。

这在数据量很小的时候是没有问题的,但是如果数据量大了,可能导致UI线程发生ANR事件。

当然你也可以写个Handler去做这些操作,只是你每次使用ContentProvider时都要再写个Handler,必然降低了效率。

因此API提供了一个操作数据库的通用方法。

 

3。如何使用AsyncQueryHandler

onXXXComplete方法的实现(可以实现任何一个或多个,当然你也可以一个也不实现,如果你不关注操作数据库的結果),在你的实现中做一些对数据库操作完成的处理。

使用时直接调用startXXX方法即可。传入的通用参数如下:

onXXXComplete方法

Object cookie,你想传给onXXXComplete方法使用的一个对象。(没有的话传递null即可。基本发现这个变量没太大作用)

Uri uri,(不解释)

 

4。AsyncQueryHandler还为我们做了什么

AsyncQueryHandler中使用了一个WeakReference<ContentResolver>对象,即ContentResolver的弱引用  作用:当contentProvied发生变化时候同步更新仍可以通过使用AsyncQueryHandler类来达到这一要求(暂时还没理解这个作用)

同时,在它执行操作数据库时,吃掉了所有的异常。见如下代码。

catch (Exception e) {
                         Log.w(TAG, e.toString());
                         cursor = null;
  }