1. 子线程的Toast怎么显示不出来?
因为Toast在创建的时候会依赖于一个Handler,并且一个Handler是需要有一个Looper才能够创建,而普通的线程是不会自动去创建一个Looper对象,比如说在某个Activity中能new一个Handler是因为Android系统在启动一个Activity的时候会默认的创建一个Looper对象。
因此为了能够在子线程中显示Toast,你可以在开启的子线程中执行Looper.prepare()来构建一个Looper,然后在显示Toast,但是不要忘记执行Looper.loop()来加载这个Looper,当然,也可以使用主线程的Looper,获取主线程的Looper的方法是Looper.getMainLooper();同时需要注意的是,同样的不能在子线程中去更新UI界面,因为Toast是相对独立于UI界面的,就好比应用虽然crash掉了,并且已经返回到home界面,但是Toast依然会在home界面显示出来。
2. 在子线程中实现显示Toast,如下:
new Thread(new Runnable() { public void run() { showToast(); } }).start();
其中showToast()方法如下:
public void showToast(String msg){ Looper.prepare(); // ****add**** Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); Looper.loop(); //****add**** }
只需要加上那两句就能在非UI线程中显示Toast。,
上面的Toast的show()方法源码如下:
public void show() { ... service.enqueueToast(pkg, tn, mDuration); //把这个toast插入到一个队列里面 ... }
还有就是Looper的prepare()、loop()方法,如下:
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(); }
3. 总结:
Toast 显示的必要条件:
Toast 显示需要出现在一个线程的消息队列中.... 很隐蔽