安卓在子线程中使用Toast

发布于:2024-09-17 ⋅ 阅读:(100) ⋅ 点赞:(0)

问题描述:
  在安卓中,ui更新必须在主线执行,Toast是一种用于在屏幕上短暂显示消息的机制,它依赖主线程来进行创建和显示消息。当我们在子线程中直接调用Toast时,就会触发Can‘t create handler inside thread that has not called Looper报错。这个错误时由于Toast内部使用了Handler来处理消息队列,并在主线程中显示Toast,而在子线程中没有默认的Looper对象可供Handler使用。
  当我们调用Toast的show方法时,会通过enqueueToast方法将toast插入消息队列中。

public void show() {
        if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
            checkState(mNextView != null || mText != null, "You must either set a text or a view");
        } else {
            if (mNextView == null) {
                throw new RuntimeException("setView must have been called");
            }
        }

        INotificationManager service = getService();
        String pkg = mContext.getOpPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;
        final int displayId = mContext.getDisplayId();

        try {
            if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
                if (mNextView != null) {
                    // It's a custom toast
                    service.enqueueToast(pkg, mToken, tn, mDuration, displayId);
                } else {
                    // It's a text toast
                    ITransientNotificationCallback callback =
                            new CallbackBinder(mCallbacks, mHandler);
                    service.enqueueTextToast(pkg, mToken, mText, mDuration, displayId, callback);
                }
            } else {
                service.enqueueToast(pkg, mToken, tn, mDuration, displayId);
            }
        } catch (RemoteException e) {
            // Empty
        }
    }

解决方案
新建一个Handler,用于子线程中使用Toast。

public class HandlerUtil {
    private static Handler mHandler;

    public static void init() {
        mHandler = new Handler();
    }

    public static void post(MyFunction func) {
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    func.apply();
                }
            });
        }
    }


    @FunctionalInterface
    public interface MyFunction {
        void apply();
    }
}

在application中调用初始化

	HandlerUtil.init();

在子线程中实现Toast。

HandlerUtil.post(()-> ToastUtil.showToast("test", 2000));

ToastUtil类可参考:安卓Toast避免重复显示


网站公告

今日签到

点亮在社区的每一天
去签到