当前位置: 首页 > article >正文

安卓在子线程中使用Toast

问题描述:
  在安卓中,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避免重复显示


http://www.kler.cn/a/308185.html

相关文章:

  • C++编程:利用环形缓冲区优化 TCP 发送流程,避免 Short Write 问题
  • Unity3D实现视频和模型融合效果
  • ISAAC SIM踩坑记录--ubuntu 22.04操作系统安装
  • 学Linux的第八天
  • SpringSecurity源码中核心类
  • 【PGCCC】Postgresql Toast 原理
  • [Linux]:进程间通信(下)
  • vue2、vue3生成二维码
  • 算法 | 基础排序算法:插入排序、选择排序、交换排序、归并排序
  • xml重点笔记(尚学堂 3h)
  • 使用 GaLore 预训练LLaMA-7B
  • 72、结合无人机进行rk3588oak-lite跟踪目标物体进行识别、跟踪、保持距离
  • Java数据结构应用(力扣题20. 有效的括号)
  • Excel 基础知识-操作手册1
  • 2024/9/16 dataloader、tensorboard、transform
  • 三十八、Go-redis快速入门
  • Celery的使用
  • C语言-结构体-详解
  • 阿里云 Quick BI使用介绍
  • 【系统架构设计师-2014年真题】案例分析-答案及详解
  • HTTPX 与 AIOHTTP 与 Requests:选择哪个?
  • 【个人博客hexo版】hexo安装时会出现的一些问题
  • 【Qt笔记】QToolBox控件详解
  • STL相关简介
  • TeamTalk梳理概括
  • JDBC注册驱动及获取连接