优化将从以下几个方面谈及
- 如何使用 Adapter
- 背景和图像
- 更新请求
- 视图和布局
- 内存分配
adapter:
最简单的方法, 最慢最不实用, 更新频率每秒传输帧数10左右
利用 convertView 回收视图, 效率提高 200%,更新频率每秒传输帧数30左右
使用 ViewHolder 模式, 效率提高 250%,更新频率每秒传输帧数40左右
背景和图像:
选择恰当的图像尺寸,视图背景图像总会填充整个视图区域:
* 图像尺寸不合适会导致自动缩放
* 避免实时缩放
* 最好预先缩放到视图大小
originalImage = Bitmap.createScaledBitmap(
originalImage, // 被缩放图像
view.getWidth(), // 视图宽度
view.getHeight(), // 视图高度
true); // 双线性过滤器
背景和图像 更新频率,预先缩放每秒传输帧数在50左右 ,自动缩放25左右
窗口背景:
* 默认情况下, 窗口有一个不透明的背景
* 有时可以不需要。
- 最高层的视图是不透明的
- 最高层的视图覆盖整个窗口 fill_parent
* 更新看不见的背景是浪费时间
* 删除窗口背景
- getWindow().setBackgroundDrawable(null);
- <item name="android:windowBackground">@null</item>
窗口背景 更新频率,有背景的每秒传输帧数在42左右 ,没有背景在50左右
更新请求:
* 当屏幕需要更新时, 调用 invalidate()
- 简单方便
- 但会更新整个视图, 太贵了
* 最好先找到无效区域, 然后调用。更有效的执行方法是只更新需要更新的区域
- invalidate(Rect dirty);
- invalidate(int left, int top, int right, int bottom);
窗口背景 更新频率:invalidate传输每秒18左右,后两个在48左右
视图和布局:
* 如果一个窗口包含很多视图
- 启动时间长 测量时间长 布局时间长 绘制时间长
* 如果视图树深度太深
- StackOverflowException 用户界面反应速度很慢
* 解决方法
- 使用 TextView 的复合 drawables 减少层次
- 使用 ViewStub 延迟展开视图
- 使用 <merge> 合并中间视图
- 使用 RelativeLayout 减少层次
- 使用自定义视图、使用自定义布局
内存分配:
* 不要创建 Java 对象,在性能敏感的代码里, 尽量避免创建 Java 对象
- 测量: onMeasure()
- 布局: onLayout()
- 绘图: dispatchDraw(), onDraw()
- 事件处理: dispatchTouchEvent(), onTouchEvent()
- Adapter: getView(), bindView()
* GC, 垃圾回收:整个程序会暂停,慢 (大约几百个毫秒
* 管理好对象
* 使用软引用,内存缓存的最佳选择
* 使用弱引用,避免内存泄露
总结:
* 用 ViewHolder 实现 Adapter 的 getView
* 为背景选择正好的图像
* 针对无效区做更新请求
* 视图和布局,越简单越好
* 避免在性能敏感路径上创建对象