Android进阶:六、在子线程中直接使用 Toast 及其原理

编程入门 行业动态 更新时间:2024-10-25 16:29:23

Android<a href=https://www.elefans.com/category/jswz/34/1769503.html style=进阶:六、在子线程中直接使用 Toast 及其原理"/>

Android进阶:六、在子线程中直接使用 Toast 及其原理

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

一般我们都把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。

写在最后

在最后,我整理了一份资料,如果有需要学习的同学可以联系我免费分享出来的,而且我们为了感谢很多支持的学者,在腾讯课堂每晚上20点有免费的直播教学,需要的同学可以来学习学习
领取方式:交流三群820655513

更多推荐

Android进阶:六、在子线程中直接使用 Toast 及其原理

本文发布于:2023-07-28 16:06:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1245031.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:进阶   线程   原理   Android   Toast

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!