美文网首页
Activity的启动过程分析

Activity的启动过程分析

作者: 詹徐照 | 来源:发表于2018-08-14 22:45 被阅读17次

    Activity启动过程

    Activity启动过程(API27).png

    Activity的Window的创建过程

    Activity启动最终会执行到ActivityThread#performLaunchActivity,调用Activity#attach
    ActivityThread

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
                activity.attach(...);
    }
    

    Activity#attach完成mWindow的初始化

    final void attach(Context context, ActivityThread aThread,...) {
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
    }
    

    Activity setContentView 的过程

    Activity setContentView .png

    Activity setContentView 会调用 PhoneWindow 的 setContentView,将 layout 填充到 DecorView 的 id 为android.id.content 的 FramLayout 中。DecorView 初始化时,会根据主题样式加载不同的布局,共同点就是都含有 id.content 的 FramLayout

    Activity启动时会在onCreate中回调setContentView,传入用户自定义布局进行渲染。

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

    getWindow()会返回mWindow,而mWindow是在Activity#attach()中被初始化的,具体实现是PhoneWindow

    PhoneWindow#setContentView()

    @Override
    public void setContentView(int layoutResID) {
        ...
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    

    mContentParent 在installDecor() 被初始化

    private void installDecor() {
        ...
        mContentParent = generateLayout(mDecor);
    }
    

    再来看看generateLayout(DecorView decor)

    /**
     * The ID that the main layout in the XML layout file should have.
     */
    public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
    
    protected ViewGroup generateLayout(DecorView decor) {
        ...
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        ...
        return contentParent;
    }
    

    Window

    public <T extends View> T findViewById(@IdRes int id) {
        return getDecorView().findViewById(id);
    }
    

    PhoneWindow

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

    installDecor()

    private void installDecor() {
        ...
        mDecor = generateDecor(-1);
    }
    

    generateDecor()

    protected DecorView generateDecor(int featureId) {
        ...
        return new DecorView(context, featureId, this, getAttributes());
    }
    

    DecorView 类声明

    public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks
    

    构造方法,如下,并没有调用任何inflate方法

    DecorView(Context context, int featureId, PhoneWindow window,
            WindowManager.LayoutParams params) {
        ...
    }
    搜索inflate,找到如下代码
    
    void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
        final View root = inflater.inflate(layoutResource, null);
        ...
        addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }
    

    在PhoneWindow搜索mDecor的引用,可以找到mDecor.onResourcesLoaded

    protected ViewGroup generateLayout(DecorView decor) {
        ...
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
    }
    

    再看看布局参数layoutResource的来历,还是在generateLayout()中,可以看到,根据feature和mIsFloating,layoutResource会被赋值成不同的layout文件

        int layoutResource;
        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
            ...
        } else {
            layoutResource = R.layout.screen_simple;
        }
    

    其中最简单的是 R.layout.screen_simple,在这里我们可以id: android:id/content ,也就是上文中提到的ID_ANDROID_CONTENT = com.android.internal.R.id.content。到这里可以看明白,Activity通过setContentView()设置的布局文件最终经过一系列的传递,传入了DecorView的FrameLayout之中。

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="vertical">
        <ViewStub android:id="@+id/action_mode_bar_stub"
                  android:inflatedId="@+id/action_mode_bar"
                  android:layout="@layout/action_mode_bar"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:theme="?attr/actionBarTheme" />
        <FrameLayout
             android:id="@android:id/content"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:foregroundInsidePadding="false"
             android:foregroundGravity="fill_horizontal|top"
             android:foreground="?android:attr/windowContentOverlay" />
    </LinearLayout>
    

    相关文章

      网友评论

          本文标题:Activity的启动过程分析

          本文链接:https://www.haomeiwen.com/subject/adsbbftx.html