天天看點

Android 頁面加載筆記作用業務

作用

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    }