如何在底层发送toast消息

本文探讨了在没有Activity上下文的情况下如何成功显示Toast信息。通过深入解析Toast的工作原理及Looper机制,给出了在非UI线程中正确使用Toast的具体方法。

问题:

在开发过程中,有如下需求,需要在协议层的最底层将服务器返回的错误信息toast出来,告知用户此次请求的错误,可是协议层底层是一个类,它没有上下文参数(context),按正常思路就是将context参数从activity层往下传到需要context的层,可是目前工程的框架已经定下来,从activity到协议层有四五层,这样一层一层地传费时,并且要将工程所有的activity都加一遍,这个工程量是非常巨大的!于是查询了一些资料,试一下能否使用全局的contexttoast

使用了myapplication保存下来的context,发现报错了Can't create handler inside thread that has not called Looper.prepare()

一般来说toast是要运行在activity才能够show出来,这次使用了全局的context显然是不行的。看一下toast的内部机制


Toast 
    public void show() 

{
      ...
        service.enqueueToast(pkg, tn, mDuration);   

//把这个toast插入到一个队列里面
        ...
    }

Looper
public static final void prepare() 

{
        if (sThreadLocal.get() != null) 

{
 throw new RuntimeException("Only one Looper may be created per thread");
        }
       sThreadLocal.set(new Looper());  

//在当前线程中创建一个Looper
    }

private Looper() {
        mQueue = new MessageQueue();  

//关键在这,创建Looper都干了什么。 其实是创建了消息队列
        mRun = true;
        mThread = Thread.currentThread();
    }

一般如果不是在主线程中又开启了新线程的话,一般都会碰到这个问题。
原因是在创建新线程的时候默认情况下不会去创建新的MessageQueue。

主线程能够toast是因为安卓封装过程中,将一个消息队列跟activity绑定了,所以可以直接使用toast.show()

于是只要在我们的代码中加上

Looper.prepare();
Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_LONG).show();
Looper.loop();

Looper.myLooper().quit();即可

 

 

总结下:Toast 显示的必要条件:
Toast 显示需要出现在一个线程的消息队列中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值