提供在工作线程同步执行主线程任务的能力,快速跳转回UI线程更新界面,不阻塞当前流程。
import android.os.Handler;
import android.os.Looper;
// 异步
// 整个类只做一件事:把任意代码块 Runnable 抛到主线程执行,并且“内部消化”所有异常,
// 让调用方既不用关心线程切换,也不用写 try-catch。
public class UiThread {
// 1. 预先拿到主线程的 Handler,后续所有 post 都靠它。
// Looper.getMainLooper() 在应用启动时就已经存在,可以放心使用。
private static final Handler MAIN = new Handler(Looper.getMainLooper());
// 2. 内部专用包装器,唯一目的:在 run() 里包一层 try-catch,
// 这样即使外部 Runnable 抛了 RuntimeException,也能被当场吃掉,不会崩溃。
private static class BaseRunnable implements Runnable {
// 3. 持有真正要执行的“用户代码”。
Runnable runnable;
// 4. 构造时把外部传进来的 Runnable 存起来。
public BaseRunnable(Runnable runnable) {
this.runnable = runnable;
}
// 5. 当 Handler 在主线程回调这个方法时,先 try 再 run,
// 任何 Exception(包括 NullPointer、IllegalState 等)都被捕获后直接忽略。
@Override
public void run() {
try {
runnable.run(); // 真正执行业务代码
} catch (Exception ignore) {
// 空 catch 块:故意不吃也不 log,达到“静默防崩”效果。
}
}
}
// 6. 对外唯一 API:不管当前身处哪个线程,只要把 Runnable 丢进来,
// 它最终都会跑到主线程执行,且异常全部被吞掉。
public static void run(Runnable r) {
// 7. 如果调用者本身就站在主线程,就直接同步执行,省去一次 post 调度。
if (Looper.myLooper() == Looper.getMainLooper()) {
try {
r.run(); // 同步跑
} catch (Exception ignore) {
// 同样吃掉异常,保持行为一致。
}
} else {
// 8. 当前是子线程,把“带防弹衣”的 BaseRunnable post 到主线程队列,
// 等主线程空闲时再去执行。
MAIN.post(new BaseRunnable(r));
}
}
}
支持 Ctrl+A 全选,Ctrl+C 复制