之前分析了IntentHandler的内部实现原理,里面用的就是HandlerThread来进行异步处理事件(想看可以点击intentHandler),然而当时并没有解释HandlerThread跟普通的Thread的区别,现在来分析下它的内部实现相关。
问题提出
1、HandlerThread是什么?
2、HandlerThread跟普通的Thread有何区别?
3、HandlerThread内部实现分析。
4、HandlerThread使用场景。
1.jpg
分析与解决问题
我们先看看源码里面对HandlerThread的解释:
/**
* Handy class for starting a new thread that has a looper. The looper can then be
* used to create handler classes. Note that start() must still be called.
*/
大概讲的意思就是:HandlerThread是一个拥有looper的子线程,这个looper可以用来创建handler类。注意,创建的HandlerThread对象的start()方法一定要执行。
很好,现在我们知道了,HandlerThread是一个继承与Thread的子线程,区别就在于,HandlerThread提供了创建handler对象的looper。
接下来,看看它的内部实现:
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;
}
构造函数里面的mPriority,优先级相关的,可以根据自己的需求去设置。
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
在Looper.prepare()里面,其实就是创建looper对象,并赋值给mLooper.onLooperPrepared()里面是空方法,我们可以重写,做一些初始化的操作,然后调用Looper.loop()方法启动了了loop。在这里,我们有一些疑惑,synchronized?notifyAll()?稍后我们在来分析,我们先看看prepare()内部实现:
public static void prepare() {
prepare(true);
}
/**
* sThreadLocal.get() will return null unless you've called prepare().
*/
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
把创建的Looper对象放到的sThreadLocal。放进去总要取出来吧,我们来看看Looper.myLooper()内部的实现:
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
贼简单,就是把之前存进去的looper对象取出来并返回。现在looper创建了,总要用上吧,这个时候就应该想到handler了,我们来看看提供的获取handler的方法getThreadHandler():
/**
* @return a shared {@link Handler} associated with this thread
* @hide
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
这个方法可以获取一个有当前子线程looper的handler对象,我们来看看getLooper(),可以看出是获取looper对象的方法:
/**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason 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;
}
这里面,isAlive()方法的意思是线程不正常运行就返回null,接着,如果looper还没创建好就wait()等待,创建后notifyAll。在这里,我们来分析下为什么会用到wait,notifyAll等相关:handler对象的创建方法(getThreadHandler())调用是在UI线程里面,but,Looper在一个线程中执行创建的,为了确保looper创建完成之后在创建handler对象,所以需要wait(),notify()来处理线程同步问题。
总结:HandlerThread其实就是一个封装了handler的Thread的子类,做好前奏工作后,让我们在线程中直接使用handler来处理一个或者多个异步操作。使用场景,就是适合那些多个并按顺序执行的耗时任务的相关需求,可以跟intentService配合使用。(intentService内部异步处理用的就是HandlerThread)
网友评论