作用
Android中的頁面展示主要是WindowManagerService負責,應用通過Binder與WMS通信,切換目前展示頁面的内容。
業務
在Activity的setContentView函數調用的是getWindow()的對應函數
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
getWindow傳回的是Window抽象類,具體的實作類是PhoneWindow,
PhoneWindow 判斷ContentParent是否為空,若為空則調用installDecor()初始化。若不為空,清除ContentParent的子View,然後調用 mLayoutInflater.inflate(layoutResID, mContentParent);渲染畫面
404 @Override
405 public void setContentView(int layoutResID) {
406 // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
407 // decor, when theme attributes and the like are crystalized. Do not check the feature
408 // before this happens.
409 if (mContentParent == null) {
410 installDecor();
411 } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
412 mContentParent.removeAllViews();
413 }
414
415 if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
416 final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
417 getContext());
418 transitionTo(newScene);
419 } else {
420 mLayoutInflater.inflate(layoutResID, mContentParent);
421 }
422 mContentParent.requestApplyInsets();
423 final Callback cb = getCallback();
424 if (cb != null && !isDestroyed()) {
425 cb.onContentChanged();
426 }
427 mContentParentExplicitlySet = true;
428 }
installDecor()函數是為了初始化contentParent,PhoneWindow内部持有一個DecorView,作為基礎ContentView使用,installDecor() 會初始化 mContentParent 和 mTitleView
2659 private void installDecor() {
2660 mForceDecorInstall = false;
2661 if (mDecor == null) {
2662 mDecor = generateDecor(-1);
2663 mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
2664 mDecor.setIsRootNamespace(true);
2665 if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
2666 mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
2667 }
2668 } else {
2669 mDecor.setWindow(this);
2670 }
2671 if (mContentParent == null) {
2672 mContentParent = generateLayout(mDecor);
2673
2674 // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
2675 mDecor.makeOptionalFitsSystemWindows();
2676
2677 final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
2678 R.id.decor_content_parent);
2679
2680 if (decorContentParent != null) {
2681 mDecorContentParent = decorContentParent;
2682 mDecorContentParent.setWindowCallback(getCallback());
2683 if (mDecorContentParent.getTitle() == null) {
2684 mDecorContentParent.setWindowTitle(mTitle);
2685 }
2686
2687 final int localFeatures = getLocalFeatures();
2688 for (int i = 0; i < FEATURE_MAX; i++) {
2689 if ((localFeatures & (1 << i)) != 0) {
2690 mDecorContentParent.initFeature(i);
2691 }
2692 }
2693
2694 mDecorContentParent.setUiOptions(mUiOptions);
2695
2696 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
2697 (mIconRes != 0 && !mDecorContentParent.hasIcon())) {
2698 mDecorContentParent.setIcon(mIconRes);
2699 } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
2700 mIconRes == 0 && !mDecorContentParent.hasIcon()) {
2701 mDecorContentParent.setIcon(
2702 getContext().getPackageManager().getDefaultActivityIcon());
2703 mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
2704 }
2705 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
2706 (mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
2707 mDecorContentParent.setLogo(mLogoRes);
2708 }
2709
2710 // Invalidate if the panel menu hasn't been created before this.
2711 // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
2712 // being called in the middle of onCreate or similar.
2713 // A pending invalidation will typically be resolved before the posted message
2714 // would run normally in order to satisfy instance state restoration.
2715 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
2716 if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
2717 invalidatePanelMenu(FEATURE_ACTION_BAR);
2718 }
2719 } else {
2720 mTitleView = findViewById(R.id.title);
2721 if (mTitleView != null) {
2722 if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
2723 final View titleContainer = findViewById(R.id.title_container);
2724 if (titleContainer != null) {
2725 titleContainer.setVisibility(View.GONE);
2726 } else {
2727 mTitleView.setVisibility(View.GONE);
2728 }
2729 mContentParent.setForeground(null);
2730 } else {
2731 mTitleView.setText(mTitle);
2732 }
2733 }
2734 }
2735
2736 if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
2737 mDecor.setBackgroundFallback(mBackgroundFallbackResource);
2738 }
2739
2740 // Only inflate or create a new TransitionManager if the caller hasn't
2741 // already set a custom one.
2742 if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
2743 if (mTransitionManager == null) {
2744 final int transitionRes = getWindowStyle().getResourceId(
2745 R.styleable.Window_windowContentTransitionManager,
2746 0);
2747 if (transitionRes != 0) {
2748 final TransitionInflater inflater = TransitionInflater.from(getContext());
2749 mTransitionManager = inflater.inflateTransitionManager(transitionRes,
2750 mContentParent);
2751 } else {
2752 mTransitionManager = new TransitionManager();
2753 }
2754 }
2755
2756 mEnterTransition = getTransition(mEnterTransition, null,
2757 R.styleable.Window_windowEnterTransition);
2758 mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
2759 R.styleable.Window_windowReturnTransition);
2760 mExitTransition = getTransition(mExitTransition, null,
2761 R.styleable.Window_windowExitTransition);
2762 mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
2763 R.styleable.Window_windowReenterTransition);
2764 mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
2765 R.styleable.Window_windowSharedElementEnterTransition);
2766 mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
2767 USE_DEFAULT_TRANSITION,
2768 R.styleable.Window_windowSharedElementReturnTransition);
2769 mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
2770 R.styleable.Window_windowSharedElementExitTransition);
2771 mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
2772 USE_DEFAULT_TRANSITION,
2773 R.styleable.Window_windowSharedElementReenterTransition);
2774 if (mAllowEnterTransitionOverlap == null) {
2775 mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
2776 R.styleable.Window_windowAllowEnterTransitionOverlap, true);
2777 }
2778 if (mAllowReturnTransitionOverlap == null) {
2779 mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
2780 R.styleable.Window_windowAllowReturnTransitionOverlap, true);
2781 }
2782 if (mBackgroundFadeDurationMillis < 0) {
2783 mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
2784 R.styleable.Window_windowTransitionBackgroundFadeDuration,
2785 DEFAULT_BACKGROUND_FADE_DURATION_MS);
2786 }
2787 if (mSharedElementsUseOverlay == null) {
2788 mSharedElementsUseOverlay = getWindowStyle().getBoolean(
2789 R.styleable.Window_windowSharedElementsUseOverlay, true);
2790 }
2791 }
2792 }
2793 }
2794
generateDecor 會直接new 一個 DecorView傳回
2292 protected DecorView generateDecor(int featureId) {
2293 // System process doesn't have application context and in that case we need to directly use
2294 // the context we have. Otherwise we want the application context, so we don't cling to the
2295 // activity.
2296 Context context;
2297 if (mUseDecorContext) {
2298 Context applicationContext = getContext().getApplicationContext();
2299 if (applicationContext == null) {
2300 context = getContext();
2301 } else {
2302 context = new DecorContext(applicationContext, getContext());
2303 if (mTheme != -1) {
2304 context.setTheme(mTheme);
2305 }
2306 }
2307 } else {
2308 context = getContext();
2309 }
2310 return new DecorView(context, featureId, this, getAttributes());
2311 }