为什么需要布局优化。
如果布局层级比较多,那么就会导致绘制的工作加剧,导致性能降低。
布局优化的原则就是减少布局的层级,能复用的就复用。
下面我们介绍下常见的布局优化方法。
1、选择低复杂度的的viewGroup,同时要避免层级太深。
满足要求的情况下尽量选择LinearLayout,FrameLayout,因为想较于RelativeLayout计算量要小。如果LinearLayout,FrameLayout中为了达到高复杂度的效果,需要嵌套,那么这时候使用RelativeLayout比较合适。
2、使用viewStub提高效率
viewStub在使用时才会加载到内存,但是要注意viewstub只能inflate一次,inflate后viewstub就会被指向的view替换。viewstub的使用
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".performOpti.PerformOptiActivity">
<Button
android:id="@+id/stub1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="56dp"
android:text="stub1"
app:layout_constraintEnd_toStartOf="@+id/stub2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/stub2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stub2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/stub1"
app:layout_constraintTop_toTopOf="@+id/stub1" />
<ViewStub
android:id="@+id/viewStub1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="@layout/view_stub_1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stub1" />
<ViewStub
android:id="@+id/viewStub2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="@layout/view_stub_2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stub1" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="@drawable/app_icon"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello world"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.yuanxuzhen.testandroid.performOpti;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewStub;
import com.yuanxuzhen.testandroid.R;
import com.yuanxuzhen.testandroid.databinding.ActivityPerformOptiBinding;
public class PerformOptiActivity extends AppCompatActivity {
ActivityPerformOptiBinding binding;
ViewStub viewStub1;
ViewStub viewStub2;
boolean viewStub1Inflate;
boolean viewStub2Inflate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityPerformOptiBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
viewStub1 = binding.viewStub1;
viewStub2 = binding.viewStub2;
binding.stub1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (viewStub2Inflate) {
viewStub2.setVisibility(View.GONE);
}
if (viewStub1Inflate ){
viewStub1.setVisibility(View.VISIBLE);
}else{
viewStub1.inflate();
viewStub1Inflate = true;
}
}
});
binding.stub2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (viewStub1Inflate) {
viewStub1.setVisibility(View.GONE);
}
if (viewStub2Inflate ){
viewStub2.setVisibility(View.VISIBLE);
}else{
viewStub2.inflate();
viewStub2Inflate = true;
}
}
});
}
}
3、避免过度绘制
要避免同一块像素区域被绘制了多次,这块要把显示不出来的view隐藏或者移除掉。
4、Listview、Gradvew等列表Item无复用,在onDraw中创建对象
5、设为GONE的view,虽然不绘制,但是会执行inflate。所以无用的view我们应该从布局中删除掉。
6、使用merge标签,来减少层级。merge 的意思是把当前布局中的内容放入父容器。
7、不把耗时操作放在activity生命周期的函数中。
渲染优化可以使用的工具
1、通过adb来确定activity的启动时间
2、通过Layout Inspector和UI Automator Viewer来分析布局