setContentView和LayoutInflater相关总结

关于setContentView:

一个布局展现在我们的面前,首先是一个Window窗口,由Window的子类PhoneWindow去实现,PhoneWindow中包含一个内部类DecorView,由系统提供的DecorView

的布局中一般包含ActionBar 、Title、以及一个id为content的FrameLayout,setContentView就是将我们Activity中的布局文件添加到这个id为content的帧布局中,所以为什么

我们给我们Activity的布局文件设置layout_width和layout_height是有效的。

<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的时候会调用ActivityThread的一系列方法,然后会调用Activity的makeVisible()将布局显示在屏幕上.

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

为什么我们要在setContentView()之前设置Activity的主题或者样式?

因为我们在setContentView()之前会默认去调用getLocalFeature()和getWindowStyle()去获取theme和style信息,

然后再去调用addView的方法进行处理

 protected ViewGroup generateLayout(DecorView decor) {
       
        TypedArray a = getWindowStyle();
        int layoutResource;
        int features = getLocalFeatures();         
       
        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");
        }     
        return contentParent;
    }

LayoutInflater的加载:

LayoutInflater的from(context)方法默认去调用context.getSystemService(...)获取一个LayoutFlater对象。

inflate(int res,ViewGroup root,boolean attachToRoot)

root  = null ? attachToRoot =true : attachToRoot =true;

root !=null? && attachToRoot = false的时候,res布局的设置的属性才有效(只包含一个View),attachToRoot = true的时候就会直接报错。

并且设置的layout_width和layout_height都无效.

如果res布局是的root是一个ViewGroup的话,子View设置的参数才是有效的。

所以其实layout_width和layout_height属性是设置在父View中子View的位置的


关于布局优化:

因为Android系统采用pull的方式解析xml布局文件,所以为了解析速度更快,我们尽量使用相对布局,减少布局层级

多使用include标签




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值