Dialog源码解析

上文中留了几个关于Dialog的问题。相信读了本文之后就能够绝了,既然要理解dialog原理,当然得从它的基类Dialog类入手,其实Dialog类也可是可以显示对话对话框的。讲之前先解释一些,下文中可能会涉及一些其他方面的知识(如theme,style,AypeValue,windowManage等等),对于这些东西我只是给出结论或作用,具体原理以后会单独写文章整理
开始进入正题,看下面这段代码,new一个对话框并显示

 new Dialog(this).show();

以上这句代表的运行结果如何呢,给大家看下;
这里写图片描述
看到没其中间一块白色区域,其他地方为黑色半透明,上没这句简单的代码是怎么样显示出这样的视图的呢,先来看第一步new Dialog(this),源码如下

 public Dialog(@NonNull Context context) {
   this(context, 0, true);
 }

public Dialog(@NonNull Context context, @StyleRes int themeResId) {
  this(context, themeResId, true);
 }

Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
    if (createContextThemeWrapper) {
         if (themeResId == 0) {
             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.setWindowManager(mWindowManager, null, null);
     w.setGravity(Gravity.CENTER);

     mListenersHandler = new ListenersHandler(this);
 }

可以发现最总会调用到Dialog的最后一个构造函数,我一步步对第三个构造函数进行分析,由于第一个函数中传给它的第二个参数为0第三个参数为true,所以代码会进入到第12行,定义一个TypedValue ,13行获取当前context的主题(也即是activity的主题,我们在AndroidManifest设定的)中R.attr.dialogTheme属性的属性值放在outValue 对象中,14行拿到该属性值对应的资源id赋值给themeResId ,16行传如刚刚的资源id对context进行包装。可以怎么理解:mContext就是通过R.attr.dialogTheme属性值对传进来的context也就是activity进行修饰过的Context对象,可以猜想R.attr.dialogTheme所设定的值就是一个style(样式)。21行拿到WindowManager对象,WindowManager就是一个窗口的管理对象,activtiy和dialog都可以理解为一个窗口,其实是acitvity和dialog都含有一Window对象,WindowManager有以下几个重要的操作:

addView(View view, ViewGroup.LayoutParams params);   向窗口添加view
updateViewLayout(View view, ViewGroup.LayoutParams params);  更新窗口view
removeView(View view);  移除窗口的view

现记住这样一个概念:只有通过这些方法我们才能看到窗口上视图的变化。接下来往下看23,24,25行就是实例化PhoneWindow对象(Window是一个抽象类,一些功能由其子类PhoneWindow实现),然后把WindowManager和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);
    }

    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;
    }

    try {
        mWindowManager.addView(mDecor, l);
        mShowing = true;

        sendShowMessage();
    } finally {
    }
}    

第一次调的时候程序会到14开始运行,14行dispatchOnCreate只是回调了一onCreate()方法,第一此创建的时候mCreate为false,系统就是在这里调用onCreate(),不信请看:

void dispatchOnCreate(Bundle savedInstanceState) {
    if (!mCreated) {
        onCreate(savedInstanceState);
        mCreated = true;
    }
}

protected void onCreate(Bundle savedInstanceState) {
}

接着又回调了onStart();方法,好重点在14行开始,getDecorView()j就是获取了该window的根视图,那么这个DecorView是怎么实例化的呢,getDecorView是在PhoneWindow类中实现的:

//PhoneWindow.java
 @Override
public final View getDecorView() {
    if (mDecor == null || mForceDecorInstall) {
        installDecor();
    }
    return mDecor;
}

一开始mDecor为null,接着往下看installDecor()

 private void installDecor() {
   mForceDecorInstall = false;
  if (mDecor == null) {
       mDecor = generateDecor(-1);
       mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
       mDecor.setIsRootNamespace(true);
       if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
           mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
       }
   } else {
       mDecor.setWindow(this);
   }
   if (mContentParent == null) {
       mContentParent = generateLayout(mDecor);

       // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
       mDecor.makeOptionalFitsSystemWindows();

       final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
               R.id.decor_content_parent);

       if (decorContentParent != null) {
           mDecorContentParent = decorContentParent;
           mDecorContentParent.setWindowCallback(getCallback());
           if (mDecorContentParent.getTitle() == null) {
               mDecorContentParent.setWindowTitle(mTitle);
           }

           final int localFeatures = getLocalFeatures();
           for (int i = 0; i < FEATURE_MAX; i++) {
               if ((localFeatures & (1 << i)) != 0) {
                   mDecorContentParent.initFeature(i);
               }
           }

           mDecorContentParent.setUiOptions(mUiOptions);

           if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
                   (mIconRes != 0 && !mDecorContentParent.hasIcon())) {
               mDecorContentParent.setIcon(mIconRes);
           } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
                   mIconRes == 0 && !mDecorContentParent.hasIcon()) {
               mDecorContentParent.setIcon(
                       getContext().getPackageManager().getDefaultActivityIcon());
               mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
           }
           if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
                   (mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
               mDecorContentParent.setLogo(mLogoRes);
           }

           // Invalidate if the panel menu hasn't been created before this.
           // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
           // being called in the middle of onCreate or similar.
           // A pending invalidation will typically be resolved before the posted message
           // would run normally in order to satisfy instance state restoration.
           PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
           if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
               invalidatePanelMenu(FEATURE_ACTION_BAR);
           }
       } else {
           mTitleView = (TextView) findViewById(R.id.title);
           if (mTitleView != null) {
               if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                   final View titleContainer = findViewById(R.id.title_container);
                   if (titleContainer != null) {
                       titleContainer.setVisibility(View.GONE);
                   } else {
                       mTitleView.setVisibility(View.GONE);
                   }
                   mContentParent.setForeground(null);
               } else {
                   mTitleView.setText(mTitle);
               }
           }
       }

       if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
           mDecor.setBackgroundFallback(mBackgroundFallbackResource);
       }

       // Only inflate or create a new TransitionManager if the caller hasn't
       // already set a custom one.
       if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
           if (mTransitionManager == null) {
               final int transitionRes = getWindowStyle().getResourceId(
                       R.styleable.Window_windowContentTransitionManager,
                       0);
               if (transitionRes != 0) {
                   final TransitionInflater inflater = TransitionInflater.from(getContext());
                   mTransitionManager = inflater.inflateTransitionManager(transitionRes,
                           mContentParent);
               } else {
                   mTransitionManager = new TransitionManager();
               }
           }

           mEnterTransition = getTransition(mEnterTransition, null,
                   R.styleable.Window_windowEnterTransition);
           mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
                   R.styleable.Window_windowReturnTransition);
           mExitTransition = getTransition(mExitTransition, null,
                   R.styleable.Window_windowExitTransition);
           mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
                   R.styleable.Window_windowReenterTransition);
           mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
                   R.styleable.Window_windowSharedElementEnterTransition);
           mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
                   USE_DEFAULT_TRANSITION,
                   R.styleable.Window_windowSharedElementReturnTransition);
           mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
                   R.styleable.Window_windowSharedElementExitTransition);
           mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
                   USE_DEFAULT_TRANSITION,
                   R.styleable.Window_windowSharedElementReenterTransition);
           if (mAllowEnterTransitionOverlap == null) {
               mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
                       R.styleable.Window_windowAllowEnterTransitionOverlap, true);
           }
           if (mAllowReturnTransitionOverlap == null) {
               mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
                       R.styleable.Window_windowAllowReturnTransitionOverlap, true);
           }
           if (mBackgroundFadeDurationMillis < 0) {
               mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
                       R.styleable.Window_windowTransitionBackgroundFadeDuration,
                       DEFAULT_BACKGROUND_FADE_DURATION_MS);
           }
           if (mSharedElementsUseOverlay == null) {
               mSharedElementsUseOverlay = getWindowStyle().getBoolean(
                       R.styleable.Window_windowSharedElementsUseOverlay, true);
           }
       }
   }
}

第四行调用 generateDecor(-1)返回的,往下看 generateDecor(-1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值