setContentView与LayoutInflater,LinearLayout和RelativeLayout及性能对比

> setContentView与LayoutInflater
-- Android应用setContentView与LayoutInflater加载解析机制源码分析:http://blog.csdn.net/yanbober/article/details/45970721
Android 探究 LayoutInflater setFactory- http://blog.csdn.net/lmj623565791/article/details/51503977

-- LayoutInflater

方式一
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(int resource, ViewGroup root);
方式二:或者通过from(Context context)获取实例

LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(int resource, ViewGroup root);

方式三:

LayoutInflater inflater = getLayoutInflater();  //调用Activity的getLayoutInflater()

其实,这三种方式本质是相同的,从源码中可以得出结论:这三种方式最终本质是都是调用的Context.getSystemService()。

-- 动态LayoutParams添加ImageView,需要设置
imageView.setScaleType(ScaleType.FIT_XY);

-- LayoutParams相当于一个Layout的信息包,它封装了Layout的位置、高、宽等信息。
1. FrameLayout下动态设置子控件居中,动态用JAVA代码要这样实现:
FrameLayout.LayoutParams lytp =newFrameLayout.LayoutParams(80,LayoutParams.WRAP_CONTENT);
lytp .gravity=Gravity.CENTER;
btn.setLayoutParams(lytp);

2. RelativeLayout下动态设置子控件居中:
RelativeLayout.LayoutParams lp=newRelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
lp.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
btn1.setLayoutParams(lp);

LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(textView.getLayoutParams());
textParams.width = dip2px(LikeXmlActivity.this,200);
textParams.height = dip2px(LikeXmlActivity.this,30);
textView.setLayoutParams(textParams);

 -- setContentView:

 Android之setContentView和LayoutInflater- http://www.cnblogs.com/devinzhang/archive/2011/12/31/2308812.html
1.常用的构造函数:
  1)setContentView(int layoutResID)
  2)setContentView(View view)
  3)setContentView(View view, ViewGroup.LayoutParams params)
2.用法
 1)setContentView(R.layout.main);
 2)LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   View view = (View) inflater.inflate(R.layout.apploader, null, true);
   setContentView(view);
3.两种用法的适用场景:
 a.setContentView()一旦调用, layout就会立刻显示UI;而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView(view)显示出来。
 b.一般在activity中通过setContentView()将界面显示出来,但是如果要在非activity中如何对控件布局进行设置操作,就需LayoutInflater动态加载。

--setContentView与LayoutInflater加载解析机制源码分析- http://blog.csdn.net/yanbober/article/details/45970721/
 setContentView整个过程:
  1.创建一个DecorView的对象mDecor,该mDecor对象将作为整个应用窗口的根视图。
  2.依据Feature等style theme创建不同的窗口修饰布局文件,并且通过findViewById获取Activity布局文件该存放的地方(窗口修饰布局文件中id为content的FrameLayout)。
  3.将Activity的布局文件添加至id为content的FrameLayout内。
 setContentView整个过程主要是如何把Activity的布局文件或者java的View添加至窗口里,重点概括为:
  1.创建一个DecorView的对象mDecor,该mDecor对象将作为整个应用窗口的根视图。
  2.依据Feature等style theme创建不同的窗口修饰布局文件,并且通过findViewById获取Activity布局文件该存放的地方(窗口修饰布局文件中id为content的FrameLayout)。
  3.将Activity的布局文件添加至id为content的FrameLayout内。
  4.当setContentView设置显示OK以后会回调Activity的onContentChanged方法。Activity的各种View的findViewById()方法等都可以放到该方法中,系统会帮忙回调。

-- 循环递归解析xml文件,解析结束回调View类的onFinishInflate方法,所以View类的onFinishInflate方法是一个空方法。
 xml文件解析实质是递归控件,解析属性的过程。所以说嵌套过深不仅效率低下还可能引起调运栈溢出。同时在解析那些tag时也有一些特殊处理,从源码看编写xml还是有很多要注意的地方的。所以说对于Android的xml来说是有一些优化技巧的(PS:布局优化可以通过hierarchyviewer来查看,通过lint也可以自动检查出来一些),如下:
1.尽量使用相对布局,减少不必要层级结构。不用解释吧?递归解析的原因。
2.使用merge属性。使用它可以有效的将某些符合条件的多余的层级优化掉。使用merge的场合主要有两处:自定义View中使用,父元素尽量是FrameLayout,当然如果父元素是其他布局,而且不是太复杂的情况下也是可以使用的;Activity中的整体布局,根元素需要是FrameLayout。但是使用merge标签还是有一些限制的,具体是:merge只能用在布局XML文件的根元素;使用merge来inflate一个布局时,必须指定一个ViewGroup作为其父元素,并且要设置inflate的attachToRoot参数为true。(参照inflate(int, ViewGroup, boolean)方法);不能在ViewStub中使用merge标签;最直观的一个原因就是ViewStub的inflate方法中根本没有attachToRoot的设置。
3.使用ViewStub。一个轻量级的页面,我们通常使用它来做预加载处理,来改善页面加载速度和提高流畅性,ViewStub本身不会占用层级,它最终会被它指定的层级取代。ViewStub也是有一些缺点,譬如:ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不能够再通过ViewStub来控制它了。所以它不适用 于需要按需显示隐藏的情况;ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。如果想操作一个具体的view,还是使用visibility属性吧;VIewStub中不能嵌套merge标签。
4.使用include。这个标签是为了布局重用。
5.控件设置widget以后对于layout_hORw-xxx设置0dp。减少系统运算次数。

-- 整个Activity的分析简单关系图:

https://i-blog.csdnimg.cn/blog_migrate/e8c5a03d2c5194a78b6d361c27c14f3e.png

 

> LinearLayout和RelativeLayout的性能对比- https://blog.csdn.net/l_215851356/article/details/56695722
  View的绘制,从ViewRoot的performTraversals()方法开始依次调用perfromMeasure、performLayout和performDraw这三个方法。这三个方法分别完成顶级View的measure、layout和draw三大流程,其中perfromMeasure会调用measure,measure又会调用onMeasure,在onMeasure方法中则会对所有子元素进行measure,这个时候measure流程就从父容器传递到子元素中了,这样就完成了一次measure过程,接着子元素会重复父容器的measure,如此反复就完成了整个View树的遍历。同理,performLayout和performDraw也分别完成perfromMeasure类似的流程。通过这三大流程,分别遍历整棵View树,就实现了Measure,Layout,Draw这一过程,View就绘制出来了。
 -- RelativeLayout和LinearLayout:
  RelativeLayout和LinearLayout两者绘制同样的界面时layout和draw的过程时间消耗相差无几,关键在于measure过程RelativeLayout比LinearLayout慢了一些。我们知道ViewGroup是没有onMeasure方法的,这个方法是交给子类自己实现的。因为不同的ViewGroup子类布局都不一样,那么onMeasure索性就全部交给他们自己实现好了。
(1)RelativeLayout慢于LinearLayout是因为RelativeLayout会让子View调用2次measure过程,而LinearLayout只需一次,但是LinearLayout有weight属性存在时,后者同样会进行两次measure。LinearLayout会避开设置过weight属性的view做第一次measure,完了再对设置过weight属性的view做第二次measure。
(2)RelativeLayout的子View如果高度和RelativeLayout不同,会引发效率问题,可以使用padding代替margin以优化此问题。
(3)在不响应层级深度的情况下,使用Linearlayout而不是RelativeLayout。
  DecorView的层级深度已知且固定的,上面一个标题栏,下面一个内容栏,采用RelativeLayout并不会降低层级深度,因此这种情况下使用LinearLayout效率更高。
  而为开发者默认新建RelativeLayout是希望开发者能采用尽量少的View层级,很多效果是需要多层LinearLayout的嵌套,这必然不如一层的RelativeLayout性能更好。因此我们应该尽量减少布局嵌套,减少层级结构,使用比如viewStub,include等技巧。可以进行较大的布局优化.

> LinearLayout

LinearLayout居右: android:layout_gravity="right|center_vertical"  

> RelativeLayout

<RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerVertical="true"
                android:layout_marginLeft="12dp" >
                <RelativeLayout
                    android:id="@+id/switch_eyes_screen_layout"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="12dp"></RelativeLayout>

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="12dp"
                    android:layout_toLeftOf="@+id/switch_eyes_screen_layout"></RelativeLayout>
</RelativeLayout>
    注意:以上XML(错误的布局)在一个父RelativeLayout有两个子RelativeLayout,并设置layout_toLeftOf属性,是不会起效果的。

解决方案:可以其中一个相对布局替换为线性布局LinearLayout等。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值