美文网首页
Dialog为什么不能用Service做context

Dialog为什么不能用Service做context

作者: 假装门口当前台 | 来源:发表于2021-02-26 19:52 被阅读0次

    直接上源码,看看Dialog初始化

    Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
            if (createContextThemeWrapper) {
                if (themeResId == ResourceId.ID_NULL) {
                    final TypedValue outValue = new TypedValue();
                    context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
                    themeResId = outValue.resourceId;
                }
                mContext = new ContextThemeWrapper(context, themeResId);
            } else {
                mContext = context;
            }
    
            mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    
            final Window w = new PhoneWindow(mContext);
            mWindow = w;
            w.setCallback(this);
            w.setOnWindowDismissedCallback(this);
            w.setOnWindowSwipeDismissedCallback(() -> {
                if (mCancelable) {
                    cancel();
                }
            });
            w.setWindowManager(mWindowManager, null, null);
            w.setGravity(Gravity.CENTER);
    
            mListenersHandler = new ListenersHandler(this);
        }
    

    可以看到其中通过context获取windowmanager,如果这个context是service,就获取不到。
    从代码可以看出,dialog也是有自己的window,而且是通过activity的wm来管理window。
    看看show函数

     public void show() {
            if (mShowing) {
                if (mDecor != null) {
                    if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
                        mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
                    }
                    mDecor.setVisibility(View.VISIBLE);
                }
                return;
            }
    
            mCanceled = false;
    
            if (!mCreated) {
                dispatchOnCreate(null);
            } else {
                // Fill the DecorView in on any configuration changes that
                // may have occured while it was removed from the WindowManager.
                final Configuration config = mContext.getResources().getConfiguration();
                mWindow.getDecorView().dispatchConfigurationChanged(config);
            }
    
            onStart();
            mDecor = mWindow.getDecorView();
    
            if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
                final ApplicationInfo info = mContext.getApplicationInfo();
                mWindow.setDefaultIcon(info.icon);
                mWindow.setDefaultLogo(info.logo);
                mActionBar = new WindowDecorActionBar(this);
            }
    
            WindowManager.LayoutParams l = mWindow.getAttributes();
            if ((l.softInputMode
                    & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
                WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
                nl.copyFrom(l);
                nl.softInputMode |=
                        WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
                l = nl;
            }
    
            mWindowManager.addView(mDecor, l);
            mShowing = true;
    
            sendShowMessage();
        }
    

    可以看出是通过window获取decorview,然后直接通过windowmanager.addView进去,这部分跟activity的加载很相似。
    在看看dismiss

        @Override
        public void dismiss() {
            if (Looper.myLooper() == mHandler.getLooper()) {
                dismissDialog();
            } else {
                mHandler.post(mDismissAction);
            }
        }
    
        void dismissDialog() {
            if (mDecor == null || !mShowing) {
                return;
            }
    
            if (mWindow.isDestroyed()) {
                Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
                return;
            }
    
            try {
                mWindowManager.removeViewImmediate(mDecor);
            } finally {
                if (mActionMode != null) {
                    mActionMode.finish();
                }
                mDecor = null;
                mWindow.closeAllPanels();
                onStop();
                mShowing = false;
    
                sendDismissMessage();
            }
        }
    

    经常使用dialog如果使用延迟dismiss,有时候会报错,说dialog attach的activity消失了。是因为activity释放了,但是这里延迟处理导致,因为activity的wm已经没了,导致window destroy。

    相关文章

      网友评论

          本文标题:Dialog为什么不能用Service做context

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