博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Toast在子线程调用的问题
阅读量:6099 次
发布时间:2019-06-20

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

Toast我们平时经常使用,但是你是否了解在子线程中要如何使用Toast呢?

Toast的一般姿势

平时我们经常在主线程中直接使用Toast,代码看起来会像下面这样

Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();

但是如果在子线程调用是不会有toast弹出的

Toast的正确姿势

如果在子线程调用那么让Toast能正常显示的方式是在它之前和之后调用Looper.prepare()和Looper.loop()

Looper.prepare();Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();Looper.loop();

原因是什么呢

我们得从源码角度来分析,看看在Toast show()的时候做了些什么

public void show() {    if (mNextView == null) {        throw new RuntimeException("setView must have been called");    }    INotificationManager service = getService();    String pkg = mContext.getOpPackageName();    TN tn = mTN;    tn.mNextView = mNextView;    try {        service.enqueueToast(pkg, tn, mDuration);    } catch (RemoteException e) {        // Empty    }}

所以Toast其实是通过NotificationManagerService来实现Toast的展示的,而传给他的参数里的 mTn又是什么呢,

其实它是Toast的一个内部类,它有两个方法,show()和hide()是用来给NotificationManagerService回调的,可以看看它的代码

private static class TN extends ITransientNotification.Stub {    ....    /**     * schedule handleShow into the right thread     */    @Override    public void show(IBinder windowToken) {        if (localLOGV) Log.v(TAG, "SHOW: " + this);        mHandler.obtainMessage(SHOW, windowToken).sendToTarget();    }    /**     * schedule handleHide into the right thread     */    @Override    public void hide() {        if (localLOGV) Log.v(TAG, "HIDE: " + this);        mHandler.obtainMessage(HIDE).sendToTarget();    }

因此可以看出来,Toast通过 NotificationManagerService来统一调度 Toast,而 NotificationManagerService回调 TN 的show()来往对应的线程发消息,

既然是handler实现,那么来看看它的实现代码,就在TN的构造方法里有这么一段

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()");    }}mHandler = new Handler(looper, null) {....

因此没有调用prepare()和启动消息队列的话,在子线程调用Toast是显示不出来的。

总结

Toast在主线程的显示只需要调用show()就可以,如果想在子线程调用,则需要在子线程启动Looper,这样才能有消息队列来承载Handler收发消息。否则子线程的Toast是不能显示的

更多Android进阶技术,面试资料系统整理分享,职业生涯规划,产品,思维,行业观察,谈天说地。可以加Android架构师群;701740775。

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

你可能感兴趣的文章
zz iOS Core Animation 简明系列教程
查看>>
oracle免安装客户端设置
查看>>
c/c++内存使用原则
查看>>
关于程序员的发展方向
查看>>
理解jsonp
查看>>
8.3心得
查看>>
HDU4546 比赛难度
查看>>
QoS 服务质量
查看>>
Vnc在Ubuntu14.04上的安装和配置 安装:
查看>>
java面试题
查看>>
导数、偏导数、梯度
查看>>
Appium移动自动化测试之安装Android SDK和JDK
查看>>
(转)深入理解最强桌面地图控件GMAP.NET --- 原理篇
查看>>
bzoj1412: [ZJOI2009]狼和羊的故事(最小割)
查看>>
bzoj4199: [Noi2015]品酒大会(后缀数组)
查看>>
Python基础之元组
查看>>
Spring入门第二课:Spring配置Bean的细节
查看>>
css3的样式 ,一个正方体
查看>>
C++字符串与指针 所有的内容也就这么多了。
查看>>
BZOJ 1063 道路设计(树形DP)
查看>>