美文网首页
Toast的显示流程

Toast的显示流程

作者: 赛非斯 | 来源:发表于2021-11-11 10:22 被阅读0次
    • 从Toast的调用开始,静态方法makeText 构造了Toast实例
    public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
                @NonNull CharSequence text, @Duration int duration) {
    }
    
    • 接着调用了show(),注意看 service.enqueueToast 方法,是把Toast作为一种通知交给NotificationManagerService 处理(因为它可能很多,必须要做个队列处理)
      这里的tn回调也作为参数传了过去
       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;
            final int displayId = mContext.getDisplayId();
            try {
                service.enqueueToast(pkg, tn, mDuration, displayId);
            } catch (RemoteException e) {
                // Empty
            }
        }
    @VisibleForTesting
        final IBinder mService = new INotificationManager.Stub() {
            // Toasts
            // =======================入队列操作=====================================================
    
            @Override
            public void enqueueToast(String pkg, ITransientNotification callback, int duration,
                    int displayId)
            {
                    record = new ToastRecord(callingPid, pkg, callback, duration, token,
                                    displayId);
                            mToastQueue.add(record);
          }
    
    • 取出消息showNextToastLocked ,回调Toast的内部类show()方法
      record.callback.show
        void showNextToastLocked() {
            ToastRecord record = mToastQueue.get(0);
            while (record != null) {
                if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
                try {
                    record.callback.show(record.token);
                    scheduleDurationReachedLocked(record);
    
                    }
                   }
            }
    //Toast->TN
      public void show(IBinder windowToken) {
                if (localLOGV) Log.v(TAG, "SHOW: " + this);
                mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
            }
    
    • 最后调用到Toast的 public void handleShow(IBinder windowToken) 方法
      其内部实现跟dialog类似,都是创建view 通过WM.addView 显示出来。

    • 问:Toast可以在子线程弹出吗
      答:肯定可以
      看他另外一个构造方法,就是需要你自己构建looper

    public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
                @NonNull CharSequence text, @Duration int duration)
    if (looper == null) {
                    // Use Looper.myLooper() if looper is not specified.
                    looper = Looper.myLooper();
                    if (looper == null) {
                        throw new RuntimeException(
                                "Can't toast on a thread that has not called Looper.prepare()");
                    }
                }
    //使用方法
    new Thread(new Runnable() {
     
                        @Override
                        public void run() {
                            Looper.prepare();
     
                            Toast.makeText(MainActivity.this, "show", Toast.LENGTH_SHORT).show();
                            Looper.loop();
                        }
                    }).start();
    

    相关文章

      网友评论

          本文标题:Toast的显示流程

          本文链接:https://www.haomeiwen.com/subject/mamwzltx.html