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();后,才会返回。
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓
PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题