嗯,这是一篇总结,内容主要是从我思维导图中记录的内容
前言
不卡顿的情况是60fps-16ms,如果绘制时间超过了这个点,人眼就会发现UI动画效果有点延迟(卡顿了)
大多数导致情况的原因是:overdraw,有大量过度绘制部分,可以用gpu选项查看
UI卡顿的原因
- 人为的在UI线程做了轻微的耗时操作
- 布局过于复杂,导致在16ms内完成绘制
- 同一时间内执行的动画过多,导致CPU/GPU负担过重
- View过度绘制导致CPU负担过重
- View过多的触发measure,layout,导致累计时间过多从而导致View频繁的重新绘制
- 内存触发的GC过多,导致暂停UI渲染 冗余的资源和逻辑也能导致
优化
1. 布局优化
- 尽量不要存在冗余嵌套,或者过于复杂的布局
- 通用的使用include引用
- 布局用户不需要看见的直接设置为gone
- 尽量使用weight取代长和宽
2.列表优化
2.1 内部类ViewHolder的使用
主要优化getView方法中每次回调用findviewByID()方法来获取一次控件的代码
//getView核心代码
ViewHolder viewHolder;
if(convertView == null){
viewHolder = new ViewHolder();
viewHolder.fruitImage = (ImageView) view.findViewByID(R.id.fruit_image);
view.setTage(viewHolder);//讲ViewHolder存储在View中
}else{
view = convertView;
viewHolder = ViewHolder view.getTag();//重获取viewHolder
}
viewHolder.fruitImage.setImageResource(fruit.getIMageID);
//内部类
class ViewHolder{
ImageView fruitImage;
}
2.2 convertView的使用,主要优化加载布局问题
listivew每次滚动都会调用gitview()方法,所以优化gitview是重中之重
大家对于 convertView = null优化方法的使用已经了然于胸,但是我那个纠结,就知道是缓存了listview里面已经加载好的view(下文会讲解)。
核心代码如下:
这部分代码很简单,如果没有缓存就加载布局,如果有缓存就直接用convertView对象。所以这样就不用滑动listview的时候
调用getView()方法每次都去加载布局了(如果改布局已经加载)。
View view;
if(convertView == null){
view = LayoutInfalter.from(getContext()).inflate(resourceID,null)
}
else{
view = convertView
}
2.3 分页分批加载数据
3.背景和图片等内存分配优化
这里深有感触,有一次进入activity的时候,卡顿,一直是以为是放了四个fragment的原因最后发现,就是因为放了一张占了四分之一的背景导致的
解决:
尽量减少不必要的背景设置
4.避免ANR