在开发中布局是必不可少的,如果某个页面的页面相对复杂,就会引起过度绘制,加载是出现卡顿等。
本篇就一部剧为切入点,主要说一下布局中的优化和某些控件的优化。
RelativeLayout 和 LinearLayout对比
之前看了一篇阿里的面试题。RelativeLayout 和 LinearLayout哪个效率高?为什么?就以这个问题开始本篇文章;
1.RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure
2.RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。
3.
在不响应层级深度的情况下,使用
Linearlayout
而不是
RelativeLayout
。
2.RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。
然而再Studio中默认是RelativeLayout,又是为什么??
默认新建
RelativeLayout
是希望开发者能采用尽量少的
View
层级,很多效果是
需要多层
LinearLayout
的嵌套,这必然不如一层的
RelativeLayout
性能更好
,
尽量减少布局嵌套,减少层级结构。
include merge ViewStub的使用和对比
在布局优化中,Android中提到的抽象布局
<include />:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width=”match_parent”
- android:layout_height=”match_parent”
- android:background="@color/bg"
-
- <include layout="@layout/toobar"/>
- <TextView android:layout_width=”match_parent”
- android:layout_height="wrap_content"
- android:text="@string/hello"
- android:padding="10dp" />
- ...
- </LinearLayout>
在<include>标签当中,我们是可以覆写所有layout属性的,即include中指定的layout属性将会覆盖掉titlebar中指定的layout属性
<merge />
可以删减多余的层级
一个垂直布局的include,这是如果include布局使用的LinearLayout就没意义了,使用的话反而减慢你的UI表现。这时可以使用。
- <merge xmlns:android="http://schemas.android.com/apk/res/android">
- <Button
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/add"/>
- <Button
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/delete"/>
- </merge>
<ViewStub />
<ViewStub />标签最大的优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。各种不常用的布局想进度条、显示错误消息等可以使用<ViewStub />标签,以减少内存使用量,加快渲染速度。<ViewStub />是一个不可见的,大小为0的View。
扫描二维码关注公众号,回复:
1105297 查看本文章
- <ViewStub
- android:id="@+id/stub_import"
- android:inflatedId="@+id/panel_import"
- android:layout="@layout/progress_overlay"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom" />
public class MainActivity extends AppCompatActivity {
private ViewStub viewStub;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewStub = (ViewStub) findViewById(R.id.vs);
//textView = (TextView) findViewById(R.id.hello_tv);空指针
}
public void inflate(View view){
viewStub.inflate();
//textView = (TextView) viewStub.findViewById(R.id.hello_tv);空指针
textView = (TextView) findViewById(R.id.hello_tv);
}
public void setData(View view){
textView.setText("DATA!!");
}
}
ViewStub只有在初始化之后才会存在,所以第一个注释中的空指针是因为ViewStub还未初始化。那第二个注释中的空指针是怎么回事呢?前面我们也说了,ViewStub在加载完成之后会移除自身,并把自身的内容转给父布局,所以此时viewStub中的内容已经不存在了,textView已经是父布局的东西了,所以不能使用viewStub来findViewById。另外,前面我们说了ViewStub只能加载一次,若调用两次inflate()的话会导致异常。