Android 高级UI设计笔记17:Android在非UI线程中显示Toast

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 显示需要出现在一个线程的消息队列中.... 很隐蔽

posted on 2016-06-02 13:55  鸿钧老祖  阅读(439)  评论(0编辑  收藏  举报

导航