子线程无法弹出Toast吗?

1、在子线程中toast会报如下异常

Can't toast on a thread that has not called Looper.prepare()

2、要想在子线程中弹Toast需要 如下:结果就会在子线程中弹出Toast

    new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(MainActivity.this, "my toast", Toast.LENGTH_SHORT).show();
                Looper.loop();

            }
        }).start();

3、解释以上现象
首先,Toast内部有两类IPC过程,第一类是Toast访问NotificationManagerService,第二类是NotificationManagerService回调Toast里面的TN接口。

    public void show() {
        if (mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }
        // 此处使用到了系统服务,也就是一类IPC
        INotificationManager service = getService();
        String pkg = mContext.getOpPackageName();
        // TN是本地的Binder类,当NMS处理Toast的显示请求是会回调TN中的方法
        TN tn = mTN;
        tn.mNextView = mNextView;

        try {
            service.enqueueToast(pkg, tn, mDuration);
        } catch (RemoteException e) {
            // Empty
        }
    }
    private static class TN extends ITransientNotification.Stub {

            mHandler = new Handler(looper, null) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case SHOW: {
                            IBinder token = (IBinder) msg.obj;
                            handleShow(token);
                            break;
                        }
                        case HIDE: {
                            handleHide();
                            // Don't do this in handleHide() because it is also invoked by
                            // handleShow()
                            mNextView = null;
                            break;
                        }
                        case CANCEL: {
                            handleHide();
                            // Don't do this in handleHide() because it is also invoked by
                            // handleShow()
                            mNextView = null;
                            try {
                                getService().cancelToast(mPackageName, TN.this);
                            } catch (RemoteException e) {
                            }
                            break;
                        }
                    }
                }
            };
        }

        /**
         * 该方法会被NMS处理显示请求时候回调,由于该方法运行在binder线程池中
         * 所以需要使用Handler将其切换到当前线程中
         */
        @Override
        public void show(IBinder windowToken) {
            if (localLOGV) Log.v(TAG, "SHOW: " + this);
            mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
        }

可以看到NMS回调TN中的show方法,show方法又运行在binder线程池中,所以使用了handler将其切换到当前线程中,而当前线程就是发送Toast请求所在的线程,而handler需要looper才能完成切换线程的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值