通用吐司

安卓开发都知道 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值