简介
- 我们知道如果在子线程中创建Handler的话,需要准备一个Looper对象,并且开启消息的轮询,如下
new Thread(new Runnable() { @Override public void run() { Looper.prepare(); Handler handler = new Handler(); Looper.loop(); } }).start();
- 那么我们在再说说这个HandlerThread
- HanderThread是继承至Thread,并且内部创建了一个Looper对象存储在当前线程的本地存储区中,然后调用了Looper中的loop方法。
- 其实Android提供这个HandlerThread就是为了避免在子线程中创建Handler时去自己创建Looper对象。
HandlerThread基本用法
//1. 创建一个HandlerThread,
//其中name是一个标记,声明线程名字,因为HandlerThread直接继承至Thread
HandlerThread mHandlerThread = new HandlerThread("name");
//2. 开启ThreadHandler,调用start()最终会回调内部实现的run方法。
mHandlerThread.start();
//3. 在Ui线程中声明一个UI线程中的Handler
Handler uiHandler = new Handler();
//4. 声明一个工作线程的Handler, 重写handleMessage方法。
Handler mWorkHandler = new Handler(mHandlerThread.getLooper()){
handleMessage(Message msg){
//此时这个handleMessage方法是运行在HandlerThread线程中的。(反正不是UI线程中的)
// 6. 调用UI线程的Handler来更新UI
uiHandler.post(new Runnable(){
run(){
//更新UI
}
})
}
}
//5. 调用工作线程发送消息
Message msg = Message.obtain();
msg.what = 1;
msg.obj = "Hello World";
mWorkHandler.sendMessage(msg)
源码解析
HandlerThread的源码分析就按照用法的顺序来进行分析了
- 创建HandlerThread 看它的构造方法
public HandlerThread(String name) { //其中name是一个标记声明线程的名字 super(name); //在这里指定线程的优先级 这里的优先级 是Process 而不是Java里面的Thread. 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); //我们可以自定义线程的优先级,默认是THREAD_PRIORITY_DEFAULT mPriority = priority; }
- 调用start方法开启线程
因为HandlerThread继承Thread调用start最终会回调run所以我们看内部的run方法就行。
- run()
public void run() { // 获取到当前线程的ID mTid = Process.myTid(); // 创建一个Looper & MeesageQueue对象。 Looper.prepare(); //通过持有锁的机制,来获取到Looper对象 synchronized (this) { mLooper = Looper.myLooper(); //发出通知,Looper对象已经创建成功了。 //这里调用notifyAll是为了唤醒下文中getLooper的方法。 notifyAll(); } //设置当前线程的优先级 Process.setThreadPriority(mPriority); //这是一个空方法,在执行线程之前进行初始化的操作,调用者可以重写该方法自行实现内部的方法。 onLooperPrepared(); //循环获取MessageQueue中的消息,并且将消息分发出去。 Looper.loop(); mTid = -1; }
- getLooper()
public Looper getLooper() { //如果当前线程没有存活,就返回null If (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. //运用到锁机制 synchronized (this) { //如果当前线程是存活状态 & mLooper对象并没有创建成功! //就阻塞线程 while (isAlive() && mLooper == null) { try { // run方法中的notifyAll就是为了通知wait方法,Looper对象创建成功了,这时就返回Looper对象了。 // 因为工作Handler调用了 ThreadHandler中的getLooper()f方法,WorkHandler是创建在UI线程的,而ThreadHandler调用start()方法是运行在子线程中的, //当UI线程要获取Looper对象的时候,如果这时子线程并没有创建好Looper对象,那么这时就处于阻塞的状态,直到Looper对象创建成功,返回Looper对象。 wait(); } catch (InterruptedException e) { } } } return mLooper; }
- quit 和 quitSafely
// quit() //在消息机制中分析过,Looper调用了quit最终是在MessageQueue中调用了,removeAllMessagesLocked()方法, //该方法是将消息队列中的所有消息退出,包括运行中的和没有运行的 public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } //quiSafely // Looper调用了quitSafely()最终调用了MessageQueue中的removeAllFutureMessagesLocked() // 该方法是将消息队列中未运行的消息给 退出,运行中的九让它继续运行了。 public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; }
问题记录
- HandlerThread中的run方法是一个无限循环,当确认ThreadHandler不在使用的情况下,调用quie或者quitSafely()来退出ThreadHandler线程中创建的MessageQueue