博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android进阶:六、在子线程中直接使用 Toast 及其原理
阅读量:5984 次
发布时间:2019-06-20

本文共 2351 字,大约阅读时间需要 7 分钟。

最近因为个人原因,很久没有更文章,感谢关注的小伙伴,望谅解!

一般我们都把Toast当做一个UI控件在主线程显示。但是有时候非想在子线程中显示Toast,就会使用Handler切换到主线程显示。

但是子线程中真的不能直接显示Toast吗?

答案是:当然可以。

那应该怎么操作呢?在当前线程中先初始化一个Looper即可!

Looper.prepare();Toast.makeText(getBaseContext(), "text", Toast.LENGTH_LONG).show();Looper.loop();复制代码

为什么在子线程中使用Toast需要初始一个Looper呢? 我们看看源代码:

public static Toast makeText(Context context, CharSequence text, @Duration int duration) {        return makeText(context, null, text, duration);    }public static Toast makeText(@NonNull Context context, @Nullable Looper looper,            @NonNull CharSequence text, @Duration int duration) {        Toast result = new Toast(context, looper);        ...        return result;    }复制代码

以上是我们使用Toast时调用的静态方法,可以看到第二个方法有个参数Looper,虽然我们平时用的时候都传入的是null,那这个Looper究竟有什么用呢?我们看看Toast的构造函数:

public Toast(@NonNull Context context, @Nullable Looper looper) {        mContext = context;        mTN = new TN(context.getPackageName(), looper);    }复制代码

可以看出这个Looper其实是TN在用,我们看看它的构造函数:

TN(String packageName, @Nullable Looper looper) {            if (looper == null) {                // Use Looper.myLooper() if looper is not specified.                looper = Looper.myLooper();                if (looper == null) {                    throw new RuntimeException(                            "Can't toast on a thread that has not called Looper.prepare()");                }            }        }复制代码

以上代码有简化。可以看出当Looper为null的时候,会通过Looper.myLooper获取一个当前的Looper。我们知道在主线程中系统已经为我们初始化了一个mainLooper,所以我们一般不用管。但是当我们子线程中如果没有初始化Looper,这里调用Looper.myLooper就获取不到一个Looper,则会抛出异常。所以当我们在子线程中使用Toast,使用Looper.prepare()方法初始化一个Looper并用Looper.loop()让它启动起来即可。

所以我们可以封装一个可以在任何线程使用的Toast。

private static Toast toast = null;    public static void showToast(Context context, String text) {        Looper myLooper = Looper.myLooper();        if (myLooper == null) {            Looper.prepare();            myLooper = Looper.myLooper();        }        if (toast == null) {            toast = Toast.makeText(context, text, Toast.LENGTH_LONG);            toast.setGravity(Gravity.CENTER, 0, 0);        }        toast.show();        if ( myLooper != null) {            Looper.loop();            myLooper.quit();        }    }复制代码

我们初始化Toast之前先判断当前线程的looper是否为空,为空则初始化一个新的myLooper,然后在调用Toast的show方法之后让looper启动起来即可。因为Looper的loop()方法是无限循环的,为了防止Looper阻塞线程,导致内存泄漏应该及时退出Looper。

喜欢的话点个赞的吧,你的赞是我更新的动力!

转载地址:http://wmgox.baihongyu.com/

你可能感兴趣的文章
提高信息安全意识对网络勒索病毒说不
查看>>
我的友情链接
查看>>
IDE---Python IDE之Eric5在window下的安装
查看>>
基本安装lnmp环境
查看>>
logstash消费阿里云kafka消息
查看>>
Oracle——条件控制语句
查看>>
day-6 and day-7:面向对象
查看>>
CSU Double Shortest Paths 湖南省第十届省赛
查看>>
webgl像机世界
查看>>
php正则怎么使用(最全最细致)
查看>>
javascript数学运算符
查看>>
LC.155. Min Stack(非优化,两个stack 同步 + -)
查看>>
交互设计[3]--点石成金
查看>>
SCCM TP4部署Office2013
查看>>
bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理...
查看>>
利用console控制台调试php代码
查看>>
讲解sed用法入门帖子
查看>>
Linux 内核已支持苹果
查看>>
【二叉树系列】二叉树课程大作业
查看>>
ASP.NET Core 2 学习笔记(三)中间件
查看>>