大家好,我是稳稳,一个曾经励志用技术改变世界,现在为失业做准备的中年奶爸程序员,与你分享生活和学习的点滴。
分享一段话:
希望总是在失望甚至绝望时产生,躺也好,卷也罢,不被大风吹倒就好。人间的事,只要生机不灭,终有抬头的一天。
好了,废话不多说了,咱们继续来学习
#面试#android
案例:某直播App在弹幕高峰期频繁崩溃,日志显示Can't create handler inside thread that has not called Looper.prepare()。
崩溃率飙升至3%,用户流失严重。
诡异现象:
关键源码路径:android.os.Handler#
// Handler.java
public Handler(@Nullable Callback callback, boolean async) {
mLooper = Looper.myLooper(); // 核心检查点
if (mLooper == null) {
throw new RuntimeException("Can't create handler inside thread...");
}
mQueue = mLooper.mQueue;
}崩溃原理:
关键源码:android.os.MessageQueue#enqueueMessage
boolean enqueueMessage(Message msg, long when) {
synchronized (this) { // 并发竞争点
msg.markInUse();
msg.when = when;
Messagep= mMessages;
// 链表插入操作可能引发线程安全问题
if (p == null || when < p.when) {
msg.next = p;
mMessages = msg;
} else {
// ...
}
}
}致命逻辑:
错误代码:
new Thread(() -> {
Handler handler = new Handler(); // 直接崩溃
}).start();解决方案:
new HandlerThread("WorkerThread") {
@Override
protected void onLooperPrepared() {
Handler handler = new Handler(getLooper()); // 安全初始化
}
}.start();原理:HandlerThread自动完成Looper初始化与循环
泄漏链路:
Activity → Handler → Message → MessageQueue → Looper → 主线程优化代码:
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null); // 清空所有消息
}错误案例:
private static Handler sHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
mTextView.setText("Hello"); // 间接持有Activity
}
};终极方案:
private staticclassSafeHandlerextendsHandler {
privatefinal WeakReference<Activity> mRef;
SafeHandler(Activity activity) {
super(Looper.getMainLooper());
mRef = newWeakReference<>(activity);
}
@Override
publicvoidhandleMessage(Message msg) {
if (mRef.get() == null) return;
// 安全操作UI
}
}原理:弱引用切断生命周期绑定
底层机制:
// ViewRootImpl.java
void postSyncBarrier() {
mTraversalBarrier = mChoreographer.postCallback(..., mTraversalRunnable);
}崩溃表现:
致命操作:
intent.putExtra("handler", myHandler); // 序列化异常替代方案:
泄漏代码:
handler.post(() -> {
webView.loadUrl("javascript:update()"); // WebView强引用Context
});解决方案:
@Override
protected void onDestroy() {
webView.destroy();
super.onDestroy();
}错误案例:
ExecutorService pool = Executors.newCachedThreadPool();
pool.execute(() -> {
Handler handler = new Handler(); // 子线程无Looper
});正确姿势:
Handler handler = new Handler(Looper.getMainLooper()); // 绑定主线程Looper
pool.execute(() -> {
handler.post(() -> updateUI()); // 安全切回主线程
});答案:
工业级代码:
public classLifecycleHandlerextendsHandlerimplementsLifecycleObserver {
privatefinal WeakReference<Context> mContextRef;
LifecycleHandler(Context context, Lifecycle lifecycle) {
super(Looper.getMainLooper());
mContextRef = newWeakReference<>(context);
lifecycle.addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
voidonDestroy() {
removeCallbacksAndMessages(null);
}
}原理:结合Jetpack生命周期组件自动回收
对比分析:
// 协程替代网络请求回调
lifecycleScope.launch {
val data = withContext(Dispatchers.IO) { fetchData() }
updateUI(data)
}Handler的线程崩溃本质是生命周期错位与线程模型误用。
掌握Looper初始化机制、MessageQueue链表操作原理、弱引用管控三板斧,可让线程通信既高效又安全。
实战工具推荐: