点击领取优惠~
1049 字
5 分钟
硬件加速 和软件绘制
硬件加速 和软件绘制
硬件加速就是运用GPU优秀的运算能力来加快渲染的速度,而通常的基于软件的绘制渲染模式是完全利用CPU来完成渲染。
在Android系统中,绘制操作可以通过软件绘制(Software Rendering)或硬件加速(Hardware Acceleration)两种方式完成,它们在实现机制和性能特性上有显著差异。
1. 基本概念对比
| 特性 | 软件绘制 | 硬件加速 |
|---|---|---|
| 绘制执行者 | CPU | GPU |
| 引入版本 | Android 1.0 | Android 3.0 (API 11) |
| 默认启用版本 | - | Android 4.0 (API 14)及以上 |
| 绘制方式 | 逐像素CPU计算 | 通过OpenGL/Direct3D指令 |
| 主要优势 | 兼容性好 | 性能高,流畅 |
| 主要劣势 | 性能低,占用CPU资源 | 部分绘制操作不支持 |
2. 技术实现差异
2.1 软件绘制流程
- Invalidate触发:View调用invalidate()
- 遍历视图树:从根View开始遍历需要重绘的View
- CPU绘制:
- 调用View.onDraw(Canvas)方法
- 通过Skia库进行软件绘制
- 结果写入Bitmap缓冲区
- 提交显示:将Bitmap传输到SurfaceFlinger显示
// 典型的软件绘制onDraw实现@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); // CPU执行这些绘制命令 canvas.drawColor(Color.WHITE); canvas.drawCircle(50, 50, 30, paint);}2.2 硬件加速流程
- Invalidate触发:View调用invalidate()
- DisplayList构建:
- 将绘制操作记录为显示列表(DisplayList)
- 不立即执行实际绘制
- RenderThread处理:
- 专用渲染线程(RenderThread)处理显示列表
- 转换为OpenGL ES/Direct3D指令
- GPU执行:GPU实际执行绘制命令
- 合成显示:通过SurfaceFlinger合成到屏幕
// 硬件加速下的onDraw实际上是在构建绘制命令列表@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); // 这些命令被记录到DisplayList,由GPU执行 canvas.drawColor(Color.WHITE); canvas.drawCircle(50, 50, 30, paint);}3. 性能关键差异
3.1 绘制性能
- 软件绘制:
- 占用CPU资源
- 复杂界面容易导致卡顿
- 每次重绘都需要完整执行
- 硬件加速:
- 利用GPU并行计算能力
- 显示列表可重用(若View未改变)
- 动画更流畅
3.2 内存占用
- 软件绘制:
- 需要维护位图缓冲区
- 大View占用内存多
- 硬件加速:
- GPU有自己的显存管理
- 总体内存占用通常更低
3.3 功能支持差异
- 硬件加速不支持的操作:
- Canvas.clipPath() (部分API级别)
- Canvas.drawTextOnPath()
- Paint.setShadowLayer() (部分效果)
- 某些Xfermode混合模式
4. 开发中的控制方式
4.1 全局配置
<application android:hardwareAccelerated="true|false"> <!-- 也可在activity级别覆盖 --> <activity android:hardwareAccelerated="false"/></application>4.2 代码控制
// 禁用单个View的硬件加速view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);// 启用硬件加速层(特殊优化场景)view.setLayerType(View.LAYER_TYPE_HARDWARE, null);5. 适用场景选择
5.1 使用软件绘制的情况
- 需要兼容API 11以下设备
- 使用了硬件加速不支持的绘制操作
- 调试绘制问题时作为对比
5.2 使用硬件加速的情况
- 大多数现代应用(API 14+)
- 需要流畅动画和滚动
- 复杂UI但较少自定义绘制
6. 常见问题解决方案
6.1 硬件加速下绘制异常
现象:某些绘制效果在开启硬件加速后显示不正确 解决:
// 方案1:禁用单个View的硬件加速view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);// 方案2:修改绘制代码避免使用不支持的操作6.2 判断当前是否硬件加速
// 检查View是否启用了硬件加速if (view.isHardwareAccelerated()) { // 硬件加速环境}// 检查Canvas是否硬件加速if (canvas.isHardwareAccelerated()) { // 硬件加速Canvas}7. 性能优化建议
- 减少过度绘制:
- 两者都受益,但硬件加速下GPU负担更明显
- 硬件加速下的优化:
- 避免频繁修改alpha属性
- 谨慎使用setLayerType(会创建离屏缓冲区)
- 重用DisplayList(保持View不变)
- 软件绘制优化:
- 缩小脏区域(invalidate时指定区域)
- 减少onDraw中的对象分配 理解这两种绘制方式的区别有助于开发者针对不同场景做出最佳选择,在兼容性和性能之间取得平衡。现代Android开发中,应优先考虑硬件加速,仅在遇到不兼容问题时回退到软件绘制。
硬件加速 和软件绘制