Activity的Window的创建过程

为了加深记忆以及方便回顾复习,所以写写博客~

上篇博客写了Activity的启动过程,如何调用的Activity的onCreate方法、onRestart方法、onStart方法、onResume方法。但是并没有涉及到我们的Window的创建过程,也就是说我们的布局是怎么在onCreate方法里加载到Window上的,以及布局是在什么显示出来的呢?
很多人都说真正Activity的启动是ActivityThread的performLaunchActivity方法完成的,其实我感觉并不是很准确,performLaunchActivity方法只是完成了Activity的创建和onCreate方法的调用,而Activity的onRestart、onStart、onResume方法的调用是从ActivityThread的handleResumeActivity方法开始的。而PerformLaunchActivity和handleResumeActivity这个两个方法都是在ActivityThread的handleLaunchActivity方法执行的。所以我觉得真正开启Activity启动流程的入口是ActivityThread的handleLaunchActivity方法。
Activity的Window的创建过程要从onCreate方法里的setContentView方法开始。

public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

这里的getWindow()是Activity里的一个成员变量Window实例mWindow,而这个mWindow是在什么时候初始化的呢?
我们在看Activity的performLaunchActivity方法的时候里面有一段代码调用了activity.attach方法。就是在这个方法里完成了mWindow的赋值和设置callback回调。

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {

        .......

        mWindow = new PhoneWindow(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);

        ........

}

Window是一个抽象类,它的具体实现是PhoneWindow类,
也就是说Activity的setContentView方法最后调用了PhoneWindow的setContentView方法。

@Override
    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.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

如果没有DecorView则创建DecorView,通过installDecor方法。省略了很多代码看主要代码:

private void installDecor() {
    if (mDecor == null) {
            mDecor = generateDecor();   
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);
}

创建DecorView是通过generateDecor方法来完成的

protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
    }

DecorView是PhoneWindow的一个内部类,继承自FrameLayout。

在installDecor方法里还有一个generateLayout方法,是将一些其他布局和系统版本及主体相关的加载到DecorView里,核心代码:

mDecor.startChanging();

        View in = mLayoutInflater.inflate(layoutResource, null);
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        mContentRoot = (ViewGroup) in;

        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        if (contentParent == null) {
            throw new RuntimeException("Window couldn't find content container view");
        }

至此DecorView创建好了,接下来就是将我们在setContentView里面设置的布局加载到DecorView的mContentParent里面了,

mLayoutInflater.inflate(layoutResID, mContentParent);

接下来会回调Activity的onContentChanged方法通知Activity的试图发生了改变。

final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }

Activity的试图已经创建完了但是现在还不是可见的。
上面我们说到ActivityThread的handleResumeActivity方法,里面除了调用了performResumeActivity方法去启动Activity的onRestart,onStart,onResume方法以外,还有一段我们可以关注的代码:

r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }

这是调用了Activity的makeVisible方法来使得我们布局可见。
看代码

void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

到这里我们的视图已经是可见的了。
我们大概再回顾一下整个过程是在Activity的onCreate方法里面加载完成了整个视图,然后在Activity的onResume方法之后再调用了Activity的makeVisible方法使得视图可见。
这就是Activity的Window的创建过程。
如有不正确的还望大家留言指正,谢谢大家~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值