Android 性能优化实例分享-内存优化 兼顾效率与性能

本文介绍了项目上线后针对预览和下载导出页面进行的内存优化,包括预览页面的内存回收改进和下载组件的缓存策略调整。通过优化,导出速度显著提升,但内存波动增大。后续措施关注内存释放和资源管理,以达到更好的用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

        项目上线一段时间后,回顾重要页面 保证更好用户体验及生产效率,做了内存优化和下载导出优化,具体效果如最后的一节的表格所示。

下面针对拍摄流程的两个页面 预览页 导出页优化实例进行介绍:

一.拍摄前预览页面优化

预览效果问题 存在内存回收不及时情况

问题描述

在预览页面两分钟的情况时: 内存回收不及时 会持续上涨到阈值 才会触发回收情况

对比图

处理前 AddCaptureActivity

处理后 AddCaptureActivity

原因

预览图未及时清除 到达阈值的时候才会回收

解决方案

对临时预览图不光置空 还要对其标记回收

效果

减少40%常驻值

后续提升

针对低性能设备可以降低预览视频 帧率及分辨率

二.拍摄保存页面

目标

业务目标:在减少导出时间 减少预览加载时间

技术目标:兼顾效率的情况下内存优化

现状

进入页面会加载预览图(全屏可滑动的全景图 ),点击下方保存按钮会下载图片。

需要导出的图片规格 6720x3360

预览组件

在compose下用个webview实现 下载好了图片转为base64通过js桥传到web中 web中负责渲染

组件布局
加载的具体实现

下载组件

通过网络请求对数据下载 默认重试时间10s 失败有toast提示 成功返回房源编辑页面

内存情况

内存常驻值为628 峰值780

内存情况

现状总结

现状情况总结:预览组件和下载导出是独立的组件

优点:独立进行加载 保证了两个业务相互独立 可以在没有预览的情况下 仍能够正常导出

缺点:导出时间长 且没有及时反馈,10s重试、占用内存峰值高

整改

第一步 打通两个组件的加载逻辑 实现缓存共用

打通两个组件的加载逻辑 实现缓存共用 实现以空间换时间实现速度提升,就是将预览组件的缓存 在导出的时候使用。

措施

通过图片缓存框架进行通过控制图片加载、缓存机制,减少无用开销、提升图片复用情况。

效果

导出速度显著提升,但是内存波动大、处在此页面时内存一直处于高位。

第二步 针对内存情况进行优化

分析

经过分析:

内存高位: 导出后bitmap在内存中并没有及时回收、缓存数据缓存了原始数据及对应UI组件大小的缩放资源

内存波动大:导出时io操作 读取bitmap 且本身io操作就会占用一定量的内存

措施
  1. 导出时 将从glide中读取bitmap保存文件后临时变量标记回收,改为获取flie形式直接copy到指定目录中。
  2. 不再缓存解码后的数据、避免浪费资源。
    diskCacheStrategy(DiskCacheStrategy.DATA)
  3. 减少预览渲染的图片大小 不展示原始图片、降低分辨率。、
  4. 在compose中及时销毁webview
    DisposableEffect(webView) { onDispose { webView?.destroy() // 销毁WebView } }
glide 磁盘缓存描述

总体流程改造后的效果

拍摄数量大于40张+,

时期

内存

效果

导出时间

优化前

内存常驻值为628 峰值780

z1 3s

SC2 弱信号下导出23.36s 正常导出 5s内

优化中

导出速度显著提升,但是内存波动大、处在此页面时内存一直处于高位。

7ms

优化后

房源编辑页常驻值为530~550

拍摄预览页为550~560

拍摄保存页内存为588~600

峰值670

7ms

### Android RecyclerView 刷新数据时的性能优化技术 #### 数据过滤提升效率 通过应用维度和度量筛选器可提高性能。当在Tableau中使用任一类型的筛选器时,会生成查询到基础数据源并限制返回的数据量,从而改善性能。简单来说,返回的数据集越小,性能表现越好[^1]。 对于RecyclerView而言,在更新列表项时应尽可能减少不必要的视图重绘操作。仅针对实际发生变动的部分执行通知更改动作,而非整体刷新整个适配器内容。这有助于降低渲染开销,进而加快界面响应速度。 ```java // 更新单个位置上的元素 notifyItemChanged(int position); // 插入新条目至指定索引处 notifyItemInserted(int position); // 移除特定下标的项目 notifyItemRemoved(int position); ``` #### 减少内存占用 考虑到DRAM作为主流计算机系统的主存组成部分具有成本效益高且易于扩展的特点;然而其保存信息的能力有限,需定期刷新以防丢失数据[^3]。因此,在开发移动应用程序特别是处理大量图片资源加载场景下,应当注意合理管理Bitmap对象生命周期以及适时回收不再使用的图像缓存来减轻RAM压力。 采用ViewHolder模式能够有效避免频繁创建销毁View实例带来的额外负担,并利用局部变量代替全局成员变量存储临时状态信息以进一步释放空间。 ```xml <!-- 布局文件 item_layout.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" ... > </LinearLayout> ``` ```java public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { @Override public void onBindViewHolder(MyViewHolder holder, int position) { } static class MyViewHolder extends RecyclerView.ViewHolder { private final TextView textView; public MyViewHolder(View view){ super(view); this.textView = view.findViewById(R.id.text_view_id); } } } ``` #### 提升交互流畅性 前端开发者专注于构建高效的用户接口,解决设计难题以增强用户体验[^4]。为了确保滚动过程中的平滑过渡效果,建议启用嵌套预取功能允许提前准备即将显示的内容片段,同时调整线程优先级使后台任务不会干扰主线程工作流。 另外还可以考虑引入DiffUtil工具类计算前后两次提交之间差异最小化变更范围,最终达到既保证视觉一致性又兼顾运行效能的目的。 ```java private List<String> mItems; ... final DiffResult result = DiffUtil.calculateDiff(new Callback() { @Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {} @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition){} }); result.dispatchUpdatesTo(this); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值