🔄 一、Looper 的核心作用
Looper 是什么?
复制代码
// Looper 是消息循环的核心,负责:
// 1. 无限循环从 MessageQueue 取消息
// 2. 将消息分发给对应的 Handler
// 3. 管理线程的消息处理能力
为什么需要 Looper?
复制代码
没有 Looper:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 发送消息 │───▶│ 消息队列 │───▶│ 没人处理 │
└─────────┘ └─────────┘ └─────────┘
有 Looper:
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 发送消息 │───▶│ 消息队列 │───▶│ Looper │───▶│ Handler │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
循环读取 ↑ │ 分发处理 ↓
└─────┘
⚙️ 二、Looper 源码深度分析
1. Looper 关键字段
复制代码
// Looper.java
public final class Looper {
// 每个线程独立的 Looper(ThreadLocal)
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
// 消息队列
private MessageQueue mQueue;
// 当前线程
private final Thread mThread;
// 主线程的 Looper(特殊处理)
private static Looper sMainLooper;
// 是否允许退出
private boolean mQuitAllowed;
// 是否已经退出
private boolean mQuitting;
// 用于日志和调试
private Printer mLogging;
private Observer mObserver;
// 构造函数(私有,通过 prepare() 创建)
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
mQuitAllowed = quitAllowed;
}
}
2. ThreadLocal 机制
复制代码
// ThreadLocal.java - 线程局部变量
public class ThreadLocal<T> {
// 每个线程有自己的 ThreadLocalMap
ThreadLocal.ThreadLocalMap threadLocals = null;
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
}
// 示例:每个线程都有独立的 Looper
Thread 1: ThreadLocal<Looper> → Looper1
Thread 2: ThreadLocal<Looper> → Looper2
Thread 3: ThreadLocal<Looper> → Looper3
🚀 三、Looper 核心方法详解
1. prepare() - 初始化 Looper
复制代码
// 准备当前线程的 Looper
public static void prepare() {
prepare(true); // 默认允许退出
}
private static void prepare(boolean quitAllowed) {
// 检查是否已经 prepare 过
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 创建 Looper 并设置到 ThreadLocal
sThreadLocal.set(new Looper(quitAllowed));
Log.d(TAG, "Looper prepared for thread: " + Thread.currentThread().getName());
}
// 主线程的特殊 prepare
public static void prepareMainLooper() {
prepare(false); // 主线程不允许退出
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
2. loop() - 消息循环的核心
复制代码
// 核心方法:开始消息循环
public static void loop() {
// 1. 获取当前线程的 Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 2. 获取消息队列
final MessageQueue queue = me.mQueue;
// 3. 清除线程的调用者标识
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 4. 开始无限循环
for (;;) {
// 5. 从队列取消息(可能阻塞)
Message msg = queue.next();
if (msg == null) {
// 没有消息表示队列正在退出
return;
}
// 6. 打印日志(如果有设置)
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
// 7. 观察者通知(用于性能监控)
final Observer observer = sObserver;
final long traceTag = me.mTraceTag;
if (observer != null) {
observer.messageDispatchStarting();
}
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
// 8. 关键:分发消息给 Handler
msg.target.dispatchMessage(msg);
} catch (Exception exception) {
// 9. 异常处理
Log.w(TAG, "Exception thrown in message dispatch", exception);
} finally {
// 10. 结束跟踪
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
// 11. 打印结束日志
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// 12. 观察者通知结束
if (observer != null) {
observer.messageDispatched();
}
// 13. 恢复调用者标识
Binder.restoreCallingIdentity(ident);
// 14. 回收消息对象
msg.recycleUnchecked();
}
}
3. myLooper() - 获取当前线程的 Looper
复制代码
// 获取当前线程的 Looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
// 获取主线程 Looper
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
// 判断当前线程是否是主线程
public static boolean isMainThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}
4. quit() / quitSafely() - 退出循环
复制代码
// 立即退出(不推荐)
public void quit() {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
mQueue.quit(false); // 立即退出
}
}
// 安全退出(等待消息处理完)
public void quitSafely() {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
mQueue.quit(true); // 安全退出
}
}
📊 四、Looper 工作原理流程图
Looper 工作流程详解
复制代码
/*
启动流程:
1. Looper.prepare() ← 创建 Looper
2. Handler 创建 ← 关联 Looper
3. Looper.loop() ← 开始循环
4. Handler 发送消息 ← 外部调用
5. MessageQueue.enqueueMessage()
6. Looper.loop() 中的 queue.next()
7. Handler.dispatchMessage()
8. 处理消息/回到步骤6
*/
消息循环状态图
复制代码
┌─────────────────────────────────────┐
│ Looper.loop() │
├─────────────────────────────────────┤
│ for (;;) { │
│ 1. Message msg = queue.next(); │
│ ├─ 队列为空 → 阻塞等待 │
│ ├─ 有同步屏障 → 找异步消息 │
│ └─ 有消息到达 → 取出消息 │
│ │
│ 2. msg.target.dispatchMessage() │
│ ├─ msg.callback != null │
│ │ → handleCallback() │
│ ├─ mCallback != null │
│ │ → mCallback.handleMessage()│
│ └─ handleMessage() │
│ │
│ 3. msg.recycleUnchecked() │
│ } │
└─────────────────────────────────────┘
🎯 五、Looper 在 Android 系统中的使用
1. 主线程 Looper(UI 线程)
复制代码
// ActivityThread.java - Android 应用主入口
public static void main(String[] args) {
// 1. 准备主线程 Looper
Looper.prepareMainLooper();
// 2. 创建 ActivityThread
ActivityThread thread = new ActivityThread();
thread.attach(false);
// 3. 设置主线程 Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// 4. 开始消息循环(永不退出)
Looper.loop();
// 理论上不会执行到这里
throw new RuntimeException("Main thread loop unexpectedly exited");
}
// 获取主线程 Handler
public static Handler getMainThreadHandler() {
return sMainThreadHandler;
}
2. HandlerThread(自带 Looper 的工作线程)
复制代码
// HandlerThread.java - Android 封装类
public class HandlerThread extends Thread {
private Looper mLooper;
@Override
public void run() {
// 1. 设置线程优先级
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 2. 准备 Looper
Looper.prepare();
synchronized (this) {
// 3. 获取 Looper
mLooper = Looper.myLooper();
notifyAll(); // 通知等待的线程
}
// 4. 开始循环
Looper.loop();
}
// 获取 Looper(会等待 Looper 创建完成)
public Looper getLooper() {
if (!isAlive()) {
return null;
}
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait(); // 等待 Looper 创建
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
// 退出
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
}
3. 子线程创建 Looper 的完整示例
复制代码
// WorkerThreadWithLooper.java
public class WorkerThreadWithLooper extends Thread {
private Looper mLooper;
private Handler mHandler;
private CountDownLatch mLatch = new CountDownLatch(1);
@Override
public void run() {
Log.d("WorkerThread", "线程启动: " + Thread.currentThread().getId());
// 1. 准备 Looper
Looper.prepare();
// 2. 获取 Looper 并通知等待的线程
synchronized (this) {
mLooper = Looper.myLooper();
mLatch.countDown(); // 通知 Looper 已准备好
}
// 3. 创建 Handler
mHandler = new Handler(mLooper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
processTask((String) msg.obj);
break;
case 2:
stopLooper();
break;
}
}
};
// 4. 开始消息循环(阻塞在这里)
Log.d("WorkerThread", "开始消息循环");
Looper.loop();
// 5. loop() 退出后执行
Log.d("WorkerThread", "消息循环结束,线程退出");
}
// 等待 Looper 创建完成
public void waitForLooper() throws InterruptedException {
mLatch.await();
}
// 获取 Handler(用于外部发送消息)
public Handler getHandler() {
return mHandler;
}
// 获取 Looper
public Looper getLooper() {
return mLooper;
}
// 处理任务
private void processTask(String task) {
Log.d("WorkerThread", "处理任务: " + task);
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("WorkerThread", "任务完成: " + task);
}
// 停止 Looper
private void stopLooper() {
if (mLooper != null) {
mLooper.quitSafely();
}
}
// 发送任务
public void sendTask(String task) {
if (mHandler != null) {
Message msg = mHandler.obtainMessage(1, task);
mHandler.sendMessage(msg);
}
}
// 延迟发送任务
public void sendDelayedTask(String task, long delay) {
if (mHandler != null) {
Message msg = mHandler.obtainMessage(1, task);
mHandler.sendMessageDelayed(msg, delay);
}
}
// 停止线程
public void stopThread() {
if (mHandler != null) {
mHandler.sendEmptyMessage(2);
}
}
}
// 使用示例
public class LooperExampleActivity extends AppCompatActivity {
private WorkerThreadWithLooper workerThread;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
// 创建并启动工作线程
workerThread = new WorkerThreadWithLooper();
workerThread.start();
// 等待 Looper 初始化完成
new Thread(() -> {
try {
workerThread.waitForLooper();
// Looper 已准备好,可以发送消息
runOnUiThread(() -> {
textView.setText("工作线程 Looper 已准备就绪");
});
// 发送任务到工作线程
workerThread.sendTask("第一个任务");
workerThread.sendDelayedTask("延迟任务", 2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 停止工作线程
if (workerThread != null) {
workerThread.stopThread();
}
}
}
⚡ 六、Looper 的高级特性
1. 同步屏障(Sync Barrier)
复制代码
// 同步屏障:确保异步消息优先执行
public class SyncBarrierExample {
public void demonstrateSyncBarrier() {
Handler handler = new Handler(Looper.getMainLooper());
MessageQueue queue = Looper.getMainLooper().getQueue();
// 1. 发送普通消息
handler.post(() -> Log.d("SyncBarrier", "普通消息 1"));
handler.post(() -> Log.d("SyncBarrier", "普通消息 2"));
// 2. 插入同步屏障(反射调用)
try {
Method postSyncBarrier = MessageQueue.class.getDeclaredMethod(
"postSyncBarrier");
postSyncBarrier.setAccessible(true);
int token = (int) postSyncBarrier.invoke(queue);
// 3. 发送异步消息(会优先执行)
Message asyncMsg = Message.obtain(handler, () -> {
Log.d("SyncBarrier", "异步消息(优先执行)");
});
asyncMsg.setAsynchronous(true);
handler.sendMessage(asyncMsg);
// 4. 发送更多普通消息(会被阻塞)
handler.post(() -> Log.d("SyncBarrier", "普通消息 3(被阻塞)"));
// 5. 移除屏障
Method removeSyncBarrier = MessageQueue.class.getDeclaredMethod(
"removeSyncBarrier", int.class);
removeSyncBarrier.setAccessible(true);
removeSyncBarrier.invoke(queue, token);
} catch (Exception e) {
e.printStackTrace();
}
}
// 输出顺序:
// 1. 异步消息(优先执行)
// 2. 普通消息 1
// 3. 普通消息 2
// 4. 普通消息 3(被阻塞)
}
2. IdleHandler(空闲处理器)
复制代码
// IdleHandler:在消息队列空闲时执行
public class IdleHandlerExample {
private int idleCount = 0;
public void useIdleHandler() {
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
// 在消息队列空闲时调用
Log.d("IdleHandler", "队列空闲,执行空闲任务 " + (++idleCount));
// 返回 true 表示保持注册,下次空闲还会调用
// 返回 false 表示只执行一次
return idleCount < 3; // 最多执行3次
}
});
}
// 实际应用:延迟加载
public void lazyLoadWithIdleHandler() {
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
// 在界面渲染完成后,空闲时加载非关键数据
loadSecondaryData();
loadRecommendations();
return false; // 只执行一次
}
});
}
}
3. Looper 与 ANR 的关系
复制代码
// ANR(Application Not Responding)产生原因
public class ANRAnalysis {
// ANR 监控机制
private void monitorANR() {
// Android 系统监控:
// 1. Input 事件 5秒内未处理 → ANR
// 2. BroadcastReceiver 10秒内未完成 → ANR
// 3. Service 20秒内未完成 → ANR
// 根本原因:Looper 的消息处理被阻塞
Handler mainHandler = new Handler(Looper.getMainLooper());
// ❌ 错误:阻塞主线程 Looper
mainHandler.post(() -> {
try {
Thread.sleep(10000); // 阻塞10秒 → ANR
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// ✅ 正确:耗时操作在子线程
new Thread(() -> {
// 耗时操作
String result = doHeavyWork();
// 完成后通知主线程
mainHandler.post(() -> updateUI(result));
}).start();
}
}
4. Looper 性能监控
复制代码
// 使用 Printer 监控 Looper 性能
public class LooperMonitor {
public void startMonitoring() {
Looper.getMainLooper().setMessageLogging(new Printer() {
private static final String START = ">>>>> Dispatching";
private static final String END = "<<<<< Finished";
private long startTime = 0;
@Override
public void println(String x) {
if (x.startsWith(START)) {
// 开始处理消息
startTime = System.currentTimeMillis();
Log.d("LooperMonitor", "开始处理消息: " + x);
} else if (x.startsWith(END)) {
// 结束处理消息
long duration = System.currentTimeMillis() - startTime;
Log.d("LooperMonitor", "消息处理完成,耗时: " + duration + "ms");
// 检测是否可能 ANR
if (duration > 100) { // 超过100ms警告
Log.w("LooperMonitor", "消息处理时间过长: " + duration + "ms");
printStackTrace();
}
}
}
private void printStackTrace() {
// 打印调用栈,找到耗时操作
StackTraceElement[] stackTrace = Looper.getMainLooper()
.getThread().getStackTrace();
for (StackTraceElement element : stackTrace) {
Log.w("LooperMonitor", element.toString());
}
}
});
}
}
🔧 七、Looper 常见问题与解决方案
问题1:Looper 未 prepare
复制代码
// ❌ 错误:在子线程直接创建 Handler
new Thread(() -> {
Handler handler = new Handler(); // 崩溃:No Looper
handler.post(() -> {});
}).start();
// ✅ 解决方案1:先 prepare
new Thread(() -> {
Looper.prepare();
Handler handler = new Handler();
Looper.loop(); // 开始循环
}).start();
// ✅ 解决方案2:使用主线程 Looper
new Thread(() -> {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> {
// 在主线程执行
});
}).start();
问题2:Looper 无法退出
复制代码
// 场景:子线程 Looper 需要正确退出
public class LooperExitExample {
private Thread workerThread;
private Handler workerHandler;
public void startWorker() {
workerThread = new Thread(() -> {
Looper.prepare();
workerHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_EXIT) {
// 退出 Looper
Looper.myLooper().quitSafely();
}
}
};
Looper.loop(); // 阻塞在这里
// Looper 退出后执行
Log.d("LooperExit", "Looper 已退出");
});
workerThread.start();
}
public void stopWorker() {
if (workerHandler != null) {
// 发送退出消息
workerHandler.sendEmptyMessage(MSG_EXIT);
}
}
// ❌ 错误:直接调用 quit(),可能丢失未处理的消息
public void stopWorkerWrong() {
if (workerHandler != null) {
workerHandler.getLooper().quit(); // 立即退出,可能丢消息
}
}
}
问题3:内存泄漏
复制代码
// 场景:Handler 持有 Activity 引用,Looper 持有 Handler
public class LeakActivity extends Activity {
// ❌ 错误:匿名 Handler 持有 Activity 引用
private Handler leakHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// 隐式持有外部 Activity 引用
updateUI();
}
};
// ✅ 解决方案:静态内部类 + 弱引用
private static class SafeHandler extends Handler {
private final WeakReference<LeakActivity> activityRef;
SafeHandler(LeakActivity activity) {
super(Looper.getMainLooper());
activityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
LeakActivity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
activity.handleMessage(msg);
}
}
}
private SafeHandler safeHandler;
@Override
protected void onDestroy() {
super.onDestroy();
// 移除所有消息
if (safeHandler != null) {
safeHandler.removeCallbacksAndMessages(null);
}
}
}
问题4:Looper 死锁
复制代码
// 场景:消息处理中又同步等待其他消息
public class DeadlockExample {
private Handler mainHandler = new Handler(Looper.getMainLooper());
private Object lock = new Object();
private boolean taskDone = false;
// ❌ 错误:在主线程同步等待
public void performTaskWithDeadlock() {
mainHandler.post(() -> {
// 发送任务到子线程
new Thread(() -> {
// 模拟耗时任务
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通知主线程任务完成
synchronized (lock) {
taskDone = true;
lock.notifyAll();
}
}).start();
// 在主线程同步等待(导致死锁)
synchronized (lock) {
while (!taskDone) {
try {
lock.wait(); // 阻塞主线程 Looper
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Log.d("Deadlock", "任务完成");
});
}
// ✅ 正确:使用回调而不是同步等待
public void performTaskCorrectly() {
mainHandler.post(() -> {
// 发送任务到子线程
new Thread(() -> {
// 模拟耗时任务
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 完成后回调到主线程
mainHandler.post(() -> {
Log.d("Correct", "任务完成,更新UI");
});
}).start();
});
}
}
📊 八、Looper 性能优化
1. 减少主线程 Looper 负担
复制代码
public class LooperOptimization {
// ❌ 错误:频繁发送小消息
private void sendManySmallMessages() {
Handler handler = new Handler(Looper.getMainLooper());
for (int i = 0; i < 100; i++) {
handler.post(() -> {
// 更新UI的很小一部分
textView.setText("更新 " + i);
});
}
}
// ✅ 正确:合并消息
private void sendBatchMessage() {
Handler handler = new Handler(Looper.getMainLooper());
// 合并数据
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 100; i++) {
builder.append("数据").append(i).append(" ");
}
// 一次发送
handler.post(() -> {
textView.setText(builder.toString());
});
}
// ✅ 使用 View.post() 替代 Handler
private void useViewPost() {
// View.post() 内部使用 Handler,但更简洁
textView.post(() -> {
textView.setText("直接更新");
});
}
}
2. 合理使用 IdleHandler
复制代码
public class IdleHandlerOptimization {
public void optimizeWithIdleHandler() {
// 在界面加载时,先加载关键数据
loadCriticalData();
// 使用 IdleHandler 加载非关键数据
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
// 在 UI 渲染完成后加载
loadNonCriticalData();
loadCacheData();
return false; // 只执行一次
}
});
}
}
3. 避免消息队列过大
复制代码
public class MessageQueueOptimization {
private Handler handler;
private static final int MAX_PENDING_MESSAGES = 50;
public void sendMessageWithLimit(Message msg) {
// 检查队列大小
if (getPendingMessageCount() > MAX_PENDING_MESSAGES) {
// 队列过大,丢弃旧消息或合并消息
handler.removeMessages(msg.what);
Log.w("Optimization", "消息队列过大,移除旧消息");
}
handler.sendMessage(msg);
}
private int getPendingMessageCount() {
// 通过反射获取消息队列大小(仅用于调试)
try {
Field field = MessageQueue.class.getDeclaredField("mMessages");
field.setAccessible(true);
Message msg = (Message) field.get(handler.getLooper().getQueue());
int count = 0;
while (msg != null) {
count++;
msg = msg.next;
}
return count;
} catch (Exception e) {
return -1;
}
}
}
🎯 九、Looper 的最佳实践
1. 主线程 Looper 使用规范
复制代码
public class MainThreadLooperRules {
// 规则1:使用 Looper.getMainLooper() 获取主线程 Looper
private Handler mainHandler = new Handler(Looper.getMainLooper());
// 规则2:不在主线程执行耗时操作
public void updateUIWithData() {
// 耗时操作在子线程
new Thread(() -> {
String data = fetchDataFromNetwork();
// 使用 Handler 更新 UI
mainHandler.post(() -> {
textView.setText(data);
});
}).start();
}
// 规则3:及时移除消息
@Override
protected void onDestroy() {
super.onDestroy();
mainHandler.removeCallbacksAndMessages(null);
}
}
2. 工作线程 Looper 使用规范
复制代码
public class WorkerThreadLooperRules {
private HandlerThread handlerThread;
private Handler workerHandler;
public void setupWorkerThread() {
// 使用 HandlerThread(Android 封装好的)
handlerThread = new HandlerThread("WorkerThread");
handlerThread.start();
// 获取 Handler
workerHandler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// 在工作线程处理消息
processTask(msg);
}
};
}
public void cleanup() {
// 正确退出
if (handlerThread != null) {
handlerThread.quitSafely();
try {
handlerThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3. Looper 调试技巧
复制代码
public class LooperDebugging {
// 方法1:设置 Logging 监控
public void setupLooperLogging() {
Looper.getMainLooper().setMessageLogging(new Printer() {
@Override
public void println(String x) {
if (x.startsWith(">>>>> Dispatching")) {
Log.d("LooperDebug", "开始处理: " + x);
} else if (x.startsWith("<<<<< Finished")) {
Log.d("LooperDebug", "处理完成: " + x);
}
}
});
}
// 方法2:检测主线程卡顿
public void detectMainThreadStuck() {
Handler handler = new Handler(Looper.getMainLooper());
// 监控消息处理时间
handler.postDelayed(() -> {
// 这个 Runnable 应该很快被执行
Log.d("LooperDebug", "监控任务执行");
}, 100);
// 如果超过 500ms 未执行,说明主线程卡顿
handler.postDelayed(() -> {
Log.w("LooperDebug", "主线程可能卡顿");
}, 600);
}
// 方法3:打印消息队列状态
public void printMessageQueueStatus() {
MessageQueue queue = Looper.getMainLooper().getQueue();
try {
Field field = MessageQueue.class.getDeclaredField("mMessages");
field.setAccessible(true);
Message msg = (Message) field.get(queue);
int count = 0;
while (msg != null) {
count++;
Log.d("QueueStatus", "消息 " + count + ": what=" + msg.what);
msg = msg.next;
}
Log.d("QueueStatus", "总消息数: " + count);
} catch (Exception e) {
e.printStackTrace();
}
}
}
🔮 十、Looper 在现代 Android 中的演进
1. Kotlin 协程替代方案
复制代码
// 使用协程代替 Handler/Looper
class CoroutineExample : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 启动协程
lifecycleScope.launch {
// 自动切换线程
val data = withContext(Dispatchers.IO) {
fetchData() // 在 IO 线程执行
}
updateUI(data) // 在主线程执行(自动切换)
}
}
}
2. LiveData 自动线程切换
复制代码
// LiveData 内部使用 Handler 进行线程切换
public class LiveDataExample extends ViewModel {
private MutableLiveData<String> data = new MutableLiveData<>();
public void loadData() {
// 在后台线程
Executors.newSingleThreadExecutor().execute(() -> {
String result = fetchData();
// 自动切换到主线程
data.postValue(result);
});
}
}
3. Executor 框架
复制代码
// 使用 Executor 管理线程
public class ExecutorExample {
private Executor mainExecutor = new Executor() {
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable command) {
handler.post(command);
}
};
private ExecutorService backgroundExecutor =
Executors.newFixedThreadPool(4);
public void executeTask(Runnable backgroundTask, Runnable uiTask) {
backgroundExecutor.execute(() -> {
backgroundTask.run();
mainExecutor.execute(uiTask);
});
}
}
✅ 总结:Looper 的核心要点
关键知识点:
-
- 每个线程最多一个 Looper(通过 ThreadLocal 保证)
-
- Looper 必须调用 prepare() 才能使用
-
- loop() 是死循环,会阻塞当前线程
-
- 主线程 Looper 不能退出
-
- 消息处理顺序:同步屏障 → 异步消息 → 普通消息
使用场景建议:
- • UI 更新 :使用主线程 Handler(
Looper.getMainLooper())
- • 后台任务 :使用
HandlerThread 或自定义线程 + Looper
- • 定时任务 :使用
Handler.postDelayed()
- • 空闲任务 :使用
IdleHandler
- • 紧急任务:使用异步消息 + 同步屏障
性能建议:
-
- ✅ 避免在主线程执行耗时操作
-
- ✅ 合理使用消息合并和批量发送
-
- ✅ 及时移除不再需要的消息
-
- ✅ 使用消息池(
Message.obtain())
-
- ✅ 监控 Looper 性能,避免 ANR