Activity加载显示基本流程

本文章是基于Android源码6.0讲解Activity加载显示基本流程

首先上一张图给大家一个直观的了解

clipboard.png

首先一个布局页面的加载是在Activity中的setContentView(R.layout.res)开始;
我们就从Acitvity源码中的setContentView方法入手

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

通过源码我们可以看到layoutResID又传给了getWindow()中的setContentView(layoutResID)方法;

mWindow = new PhoneWindow(this);
public Window getWindow() {
    return mWindow;
}

getWindow()返回的是PhoneWindow的对象
我们来看PhoneWindow中setContentView(layoutResID)方法
PhoneWindow是一个隐藏类,在源码sources/andorid-23/com/android/internal/policy中

PhoneWindow中setContentView方法

 @Override
public void setContentView(int layoutResID) {
   if (mContentParent == null) {
        installDecor();//Activity新创建时mContentParent 为空,调用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();
    }
}

我们来看PhoneWindow中installDecor()方法中的关键部分

private void installDecor() {
    if (mDecor == null) { 
        mDecor = generateDecor(); //@1
        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        mDecor.setIsRootNamespace(true);
        if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
        }
    }
    if (mContentParent == null) {
        mContentParent = generateLayout(mDecor); //@2

        ...
    }
    mLayoutInflater.inflate(layoutResID, mContentParent);//@3
}

在PhoneWindow源码中声明了 private DecorView mDecor;
DecorView 是PhoneWindow中的一个内部类继承了FrameLayout,是一个帧布局

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
    ...
}

@1 首先调用mDecor = generateDecor();返回的是一个 DecorView的对象,这就是所有页面的跟布局

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

@2 其次调用mContentParent = generateLayout(mDecor);

protected ViewGroup generateLayout(DecorView decor) {
...
    } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
        layoutResource = R.layout.screen_simple_overlay_action_mode;
    } else {
        // Embedded, so no decoration is needed.
        layoutResource = R.layout.screen_simple;
        // System.out.println("Simple!");
    }
    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);
    ...
    return contentParent;
}

这里的layoutResource是源码中的布局,我们来看一下R.layout.screen_simple
在sdk/platforms/android-23/data/res/layout路径中

<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>

R.layout.screen_simple就是一个简单的线性布局,通过mLayoutInflater.inflate和decor.addView添加到DecorView中,
再通过ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);把R.layout.screen_simple中id
为id/content的Framelayout赋值给contentParent
@3 最后通过mLayoutInflater.inflate(layoutResID, mContentParent);把我们写的布局添加到mContentParent中。

未完待续...

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值