通用吐司

来源:互联网 发布:linux查看samba用户 编辑:程序博客网 时间:2024/04/27 13:29

安卓开发都知道 Toast不能在子线程使用

Toast的使用方式:Toast.makeText(context, msg, Toast.LENGTH_LONG).show()。

当在非UI线程使用时会抛出:Can't create handler inside thread that has not called Looper.prepare()

从异常可以看出直接原因是没有调用Looper.prepare(),所以可以这样写

Looper.prepare();  Toast.makeText(context, msg, Toast.LENGTH_LONG).show();  Looper.loop();  

那么为什么不能在非UI线程使用呢?查看源码

 /**     * Show the view for the specified duration.     */    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        }    }

Tn对象的show:

 /**         * schedule handleShow into the right thread         */        @Override        public void show() {            if (localLOGV) Log.v(TAG, "SHOW: " + this);            mHandler.post(mShow);        }

可以看到调用了Handler的post方法,然而:

 final Handler mHandler = new Handler();  

handler使用了当前线程的looper,因为工作线程若没有初始化其Looper,也就没有MessageQueue来管理Handler消息,Handler的post()方法将会返回失败(false)。

创建通用Toast

我们可以根据源码来设计一个非UI线程的Toast,方法是使用UI线程的looper,
创建handler:

 public static Handler handler=new Handler(Looper.getMainLooper());

此时的show是这样的

  public static void showToast(final Context context,             final String content) {            if (Looper.myLooper()==Looper.getMainLooper())             {//主线程                show(context,content);            }else             {//子线程                handler.post(new Runnable()                 {                    @Override                    public void run()                     {                        show(context,content);                    }                });            }        }

根据当前的lopper是否为UI的选择弹出方式是直接显示还是高仿源码调用主线程的handler.post()方法显示。

 public static void show(Context context,String content){            if (TextUtils.isEmpty(content)) {                return;            }            //toast 为全局的 private static Toast toast;            if (toast == null) {                toast = Toast.makeText(context,                             content,                              Toast.LENGTH_SHORT);            } else {                toast.setText(content);            }            toast.show();        }

此处,判断Toast是否为null,避免了多次调用反复弹出,根据个人需要修改即可。

0 0