Caused by: java.lang.NullPointerException: Can't toast on a thread that has not

1,521 阅读1分钟

toast还有坑,有一个优化toast的任务,我以为一个小时就应该搞定了,没想到有个坑

     Caused by: java.lang.NullPointerException: Can't toast on a thread that has not called Looper.prepare()
        at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:157)
        at android.widget.Toast.getLooper(Toast.java:179)
        at android.widget.Toast.<init>(Toast.java:164)
        at android.widget.Toast.<init>(Toast.java:154)

啥意思呢,就是子线程要更新主线程的UI,那肯定是不行的,我看到网上有一个解决方案

需要在子线程中手动创建一个Looper 参考# 解决java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()

但是我的toast是一个util类,项目中调用的地方有成百上千,我不可能把所有的都筛查一遍吧

我想到原来项目中用了一个第三方的库,可以直接显示,为啥人家可以呢,我就看了看它的源码,发现

UtilsBridge.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        cancel();
        IToast iToast = newToast(utils);
        ToastUtils.sWeakToast = new WeakReference<>(iToast);
        if (view != null) {
            iToast.setToastView(view);
        } else {
            iToast.setToastView(text);
        }
        iToast.show(duration);
    }
});

最终是调用了

public static void runOnUiThread(final Runnable runnable) {
    if (Looper.myLooper() == Looper.getMainLooper()) {
        runnable.run();
    } else {
        HANDLER.post(runnable);
    }
}

好的,现在水落石出了,我也参考着这个写一下,判断是不是主线程,是的话,直接显示,不是的话,那就用handle辅助一下。ok