前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Activity 的 Window 创建过程

Activity 的 Window 创建过程

作者头像
Yif
发布2019-12-26 15:29:42
7030
发布2019-12-26 15:29:42
举报
文章被收录于专栏:Android 进阶

Activity 的 Window 创建过程

Activity Window创建最终在ActivityThread 中的performLaunchActivity方法中,调用Activity的attach方法创建。

调用mWindow = new PhoneWindow(this, window, activityConfigCallback);进行初始化操作; Activity中有一个成员为Window,其实例化对象为PhoneWindow,PhoneWindow为抽象Window类的实现类。

  • Window是一个抽象类,提供了绘制窗口的一组通用API。
  • PhoneWindowWindow的具体继承实现类。而且该类内部包含了一个DecorView对象,该DecorView对象是所有应用窗口(Activity界面)的根View。
  • DecorViewPhoneWindow的内部类,是FrameLayout的子类,是对FrameLayout进行功能的修饰(所以叫DecorXXX),是所有应用窗口的根View

Activity、View、Window关系

一句话概括,Activity像工匠,View像窗花,window像窗户,LayoutInflater像剪刀,Xml像窗花图纸。Activity根据他们不同职能,并且与他们相互配合像我们展示灵活与精致的界面

View如何与Activity进行关联

View并不是直接与Activity关联,而是通过Window这个中间人,Window才是直接关联到Activity上的

Window如何与Activity进行关联

每一个Activity包含一个PhoneWindow,并且PhoneWindow是抽象类Window的子类,setContentView让View与Window关联,Activity与Window关联

总结

Activity包含一个PhoneWindow,而PhoneWindow继承Window,Activity通过setContentView将View设置到PhoneWindow上,而View通过WindowManageraddView,removeView,updateView来对View进行管理,Window的添加过程与Activity启动流程都是一个IPC过程。Activity启动完需要通过AMS完成,而Window添加过程需要通过WindowSession完成。

Activity 视图附加到Window上

通过ActivitysetContentView方法来实现

代码语言:javascript
复制
//FEATURE_CONTENT_TRANSITIONS 转场动画
setContentView(R.layout.activity_test_event);

最后调用的是Activity的setContentView方法

代码语言:javascript
复制
public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

getWindow返回的是window对象,而window是抽象方法由PhoneWindow实现,所以调用是PhoneWindowsetContentView方法

代码语言:javascript
复制
public void setContentView(int layoutResID) {
    // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
    // decor, when theme attributes and the like are crystalized. Do not check the feature
    // before this happens.
//判断mContentParent是否为空,这里它是一个viewgroup
    if (mContentParent == null) {
//为空,进行初始化操作
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
//不为空,移除之前所以的子view
        mContentParent.removeAllViews();
    }
//判断是否含有转场动画
    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
//没有使用此方法加载布局,将布局加载到mContentParent中
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}
private void installDecor() {
    mForceDecorInstall = false;
//DecorView为空进行初始化
    if (mDecor == null) {
        mDecor = generateDecor(-1);
        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        mDecor.setIsRootNamespace(true);
        if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
        }
    } else {
//不为空,与PhoneWindow进行关联
        mDecor.setWindow(this);
    }
    if (mContentParent == null) {
//初始化操作,方法内部通过findviewbyid寻找是否存在id为content的Android内部布局FragmentLayout,有返回,
//没有抛异常
        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);
            }
            PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
            if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
                invalidatePanelMenu(FEATURE_ACTION_BAR);
            }
        } else {
            mTitleView = 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);
            }
        }
    }
}
总结:
  1. 创建一个DecorViewmDecor对象,用于做为整个应用窗口的根视图;
  2. view添加到DecorViewmContentParent中;
  3. 依据Featurestyle theme创建不同的窗口修饰布局文件,并且通过findViewById获取Activity布局文件该存放的地方(窗口修饰布局文件中id为content的FrameLayout);
  4. Activity的布局文件添加至id为contentFrameLayout内;
  5. 回调Activity的onContentChanged方法通知Activity视图发生改变,onContentChanged是一个空的实现,可以自己在Activity中实现 final Callback cb = getCallback();     if (cb != null && !isDestroyed()) {         cb.onContentChanged();     }

但是此时DecorView并没有被添加到WindowManager中,没有被识别,无法获取Window的具体功能,需要调用Activity中的makeVisible方法,DecorView才能真正的显示出来。最后ActivityWindow就创建完成了。

代码语言:javascript
复制
 void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年9月18日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Activity 的 Window 创建过程
    • Activity、View、Window关系
      • View如何与Activity进行关联
      • Window如何与Activity进行关联
      • 总结
    • Activity 视图附加到Window上
      • 总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档