如何优化Android中ContentResolver查询图片视频文件夹的速度
性能优化建议
以下优化点按收益从高到低排序,全部落地后9000个媒体文件的处理耗时预计可压缩到100ms以内:
1. MediaStore查询层优化(最大收益点)
- 调整排序逻辑减少Cursor操作:当前你按
DATE_ADDED正序查询,再调用moveToLast倒序遍历,完全可以直接修改排序语句为${MediaStore.Files.FileColumns.DATE_ADDED} DESC,直接正序遍历Cursor即可,避免Cursor倒走的额外开销。 - 优化查询字段减少不必要的字符串操作:
给projection新增MediaStore.Files.FileColumns.BUCKET_ID、MediaStore.Files.FileColumns.MEDIA_TYPE、MediaStore.Files.FileColumns.RELATIVE_PATH三个字段:- 用
BUCKET_ID(Long类型)作为folderMap的key,替代当前你自己切割路径得到的字符串key,哈希映射查找效率提升50%以上,同时去掉path.substringBeforeLast("/")的字符串切割开销。 - 用
MEDIA_TYPE的Int值判断是否为视频,替代当前mimeType.contains("video")的字符串匹配操作,判断效率提升数倍。 - 用
RELATIVE_PATH判断是否为相机文件夹,替代path.contains(cameraPathName)的字符串匹配,同时适配Android 10+以上废弃DATA字段的规则。
- 用
- 优化查询条件减少SQL解析开销:将当前硬拼接的selection改为占位符写法,系统解析SQL速度更快,同时避免注入风险:
val selection = "${MediaStore.Files.FileColumns.MEDIA_TYPE} IN (?,?)" val selectionArgs = arrayOf( MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(), MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString() )
2. 遍历逻辑优化
- 删除冗余IO操作:当前你在
bucketPath为空时创建File对象拿父路径,属于磁盘IO操作,新增BUCKET_ID和RELATIVE_PATH字段后不会出现bucketPath为空的情况,直接删除这段File创建逻辑即可,可减少大量IO开销。 - 避免集合冗余拷贝:当前你先把所有媒体存入
allMedias、allVideos,后续又调用allMedia.images.addAll(allMedias)做了一次全量元素拷贝,直接将allMedia.images引用指向allMedias即可,无需重复添加元素,省掉9000次元素插入开销。 - 相机文件夹逻辑前置:遍历过程中识别到相机文件夹后单独存储,不要先存入folderMap再remove后插入列表头部,省掉一次Map的put和remove操作。
3. 集合操作优化
- 预初始化集合容量:当前的
allMedias、allVideos、folderMap都没有设置初始容量,ArrayList扩容时会触发多次数组拷贝,可提前查询媒体总数给allMedias设置初始容量,folderMap按设备平均相册数量设置初始值100,避免扩容开销。
4. 稳定性优化(无额外性能损耗)
将Cursor的关闭逻辑放到finally代码块中,避免异常时Cursor未关闭造成资源泄露。
内容的提问来源于stack exchange,提问作者Mohan K
相关产品推荐
相关产品推荐

