7.5 KiB
7.5 KiB
Handler机制
目录
Handler原理
Handler 作用
// Handler:用于线程间通信
// 主线程 → 子线程:通过 Handler 发送消息
// 子线程 → 主线程:通过 Handler 更新 UI
Handler 架构
┌─────────┐
│ Handler │ ←─── 发送和处理消息
└────┬────┘
│
┌────▼────┐
│ Looper │ ←─── 消息循环
└────┬────┘
│
┌────▼────┐
│MessageQueue│ ←─── 消息队列
└────┬────┘
│
┌────▼────┐
│ Message │ ←─── 消息对象
└─────────┘
Looper机制
Looper 作用
// Looper:消息循环器
// 从 MessageQueue 中取出消息,分发给 Handler 处理
// 主线程 Looper
Looper looper = Looper.getMainLooper();
// 子线程 Looper
class MyThread extends Thread {
@Override
public void run() {
Looper.prepare(); // 创建 Looper
Looper.loop(); // 开始循环
}
}
Looper 原理
// Looper.prepare()
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
// Looper.loop()
public static void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // 阻塞等待消息
if (msg == null) {
return;
}
msg.target.dispatchMessage(msg); // 分发消息
msg.recycleUnchecked();
}
}
MessageQueue
MessageQueue 原理
// MessageQueue:消息队列
// 使用单链表存储消息
// 按时间排序,时间早的在前面
// 消息入队
boolean enqueueMessage(Message msg, long when) {
// 插入消息到队列
// 按时间排序
}
// 消息出队
Message next() {
// 取出消息
// 如果队列为空,阻塞等待
}
消息优先级
// 消息按时间排序
// when 值小的先执行
// 立即执行
handler.sendMessage(msg); // when = 0
// 延迟执行
handler.sendMessageDelayed(msg, 1000); // when = SystemClock.uptimeMillis() + 1000
Message传递
发送消息
// 方式1:sendMessage
Message msg = Message.obtain();
msg.what = 1;
msg.obj = "Data";
handler.sendMessage(msg);
// 方式2:sendMessageDelayed
handler.sendMessageDelayed(msg, 1000);
// 方式3:post
handler.post(new Runnable() {
@Override
public void run() {
// 执行代码
}
});
// 方式4:postDelayed
handler.postDelayed(runnable, 1000);
处理消息
// Handler 处理消息
public class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 处理消息
String data = (String) msg.obj;
break;
}
}
}
// 或使用 Callback
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
// 处理消息
return true; // true 表示已处理,不再调用 handleMessage
}
});
消息分发流程
// dispatchMessage 流程
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
// 1. 优先执行 Runnable
handleCallback(msg);
} else {
if (mCallback != null) {
// 2. 执行 Callback
if (mCallback.handleMessage(msg)) {
return;
}
}
// 3. 执行 handleMessage
handleMessage(msg);
}
}
Handler内存泄漏
泄漏原因
// ❌ 问题:Handler 持有 Activity 引用
public class MainActivity extends AppCompatActivity {
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// Handler 持有 Activity 的隐式引用
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler.postDelayed(new Runnable() {
@Override
public void run() {
// 如果 Activity 已销毁,但 Handler 还在处理消息
}
}, 10000);
}
}
解决方案
方案1:静态内部类 + WeakReference
// ✅ 解决方案1:静态内部类 + WeakReference
public class MainActivity extends AppCompatActivity {
private static class MyHandler extends Handler {
private WeakReference<MainActivity> mActivity;
MyHandler(MainActivity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = mActivity.get();
if (activity == null || activity.isFinishing()) {
return;
}
// 处理消息
}
}
private MyHandler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new MyHandler(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
}
}
方案2:使用主线程 Looper
// ✅ 解决方案2:使用主线程 Looper
Handler handler = new Handler(Looper.getMainLooper());
方案3:及时移除消息
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
}
Handler最佳实践
1. 避免内存泄漏
// 使用静态内部类 + WeakReference
// 或使用主线程 Looper
2. 及时移除消息
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
}
3. 使用 Message.obtain()
// ✅ 推荐:复用 Message 对象
Message msg = Message.obtain();
// ❌ 不推荐:创建新对象
Message msg = new Message();
面试常见问题
Q1: Handler 的原理?
答案: Handler → Looper → MessageQueue → Message
- Handler 发送消息到 MessageQueue
- Looper 从 MessageQueue 取出消息
- Handler 处理消息
Q2: Looper 的作用?
答案:
- 消息循环器
- 从 MessageQueue 取出消息
- 分发给 Handler 处理
Q3: Handler 为什么会导致内存泄漏?
答案:
- Handler 持有 Activity 的隐式引用
- Message 持有 Handler 的引用
- MessageQueue 持有 Message 的引用
- 如果 Handler 还有未处理的消息,Activity 无法被回收
Q4: 如何避免 Handler 内存泄漏?
答案:
- 使用静态内部类 + WeakReference
- 使用主线程 Looper
- 及时移除消息(onDestroy 中)
Q5: Handler、Looper、MessageQueue 的关系?
答案:
- Handler:发送和处理消息
- Looper:消息循环,从 MessageQueue 取消息
- MessageQueue:消息队列,存储消息
- 一个线程只有一个 Looper,一个 Looper 只有一个 MessageQueue,可以有多个 Handler
最后更新:2024年