1.一个线程有几个Handler?
一个线程可以有多个handler
2.一个线程有几个looper?如何保证
一个线程只有一个looper,是通过ThreadLocal 来保证的,每个线程都有ThreadLocal.ThreadLocalMap 变量
ThreadLocal.ThreadLocalMap threadLocals = null;
map对象,key为ThreadLocal本身,value为Object的对象,也就是一个ThreadLocal 对应一个looper对象,
在looper中定义的TheadLocal是静态final的,也就是唯一的
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
在looper的prepare方法中会进行设置,如果设置过了就会抛异常
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
3.子线程可以创建handler吗
可以
4.多个Handler忘messageQueue中添加数据,内部是如何保证线程安全的
每个handler发送消息都会绑定发送消息的handler,在messageQuue取出后会找到对应的handler 进行处理
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Looper 中loopOnce:
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
5.Looper.loop()为什么不会阻塞主线程
因为android 是事件驱动的,通过发送消息改变组件的生命周期,
6.MessageQueue 的数据结构是什么样子
消息队列
7.Handler内存泄露场景有哪些,如何避免
延迟消息导致的内存泄露,activity销毁后还有消息没有发送,避免方式:弱引用,或者移除Hanlder的消息
8.IntentService源码解析
Service本身是位于主线程,不能进行耗时操作,IntentService 继承于Service,内部包含了HandlerThread,相当于
开了个线程,通过拿到HanlderThread的looper,创建一个子线程的Handler。
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
通过发送子线程handler 发送消息,最终执行Hanlder的handleMessage,而handleMessage 中调用了抽象方法onHandleIntent。
故继承了HanlderService的类,就具备了子线程的能力
9.HandlerThread源码解析
HandlerThread继承与Thead,在run方法中创建了Looper
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
getLooper()方法
public Looper getLooper() {
if (!isAlive()) {
return null;
}
boolean wasInterrupted = false;
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
wasInterrupted = true;
}
}
}
/*
* We may need to restore the thread's interrupted flag, because it may
* have been cleared above since we eat InterruptedExceptions
*/
if (wasInterrupted) {
Thread.currentThread().interrupt();
}
return mLooper;
}
外部可以用过getThreadHandler拿到子线程的Hanlder,发送消息给子线程处理
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
getLooper 方法能确保存在handler,不存在就一直等待wait,直到looper被创建,执行notifyAll();后,才会返回