加载页面数据时内存突然爆满_优化相册加载速度

公司App的相册加载速度太慢了,之前提过一次,然后一个同事就去做这个优化工作了,这两天突然想起来了,就看一下他优化的效果,发现加载速度还是太慢。以我的HUAWEI ANE-LX2 Android 8.0.0 API 26测试机为例,8000多张图片首次加载时间大约4s左右,而且如果切换排序,这个时间也挺长,总之,我认为体验效果非常不好,最好优化到1s左右。

我先看了下他优化的代码,就是用了IntentService开一个线程去请求系统数据库;然后cursor.moveToNext()读取字段并构造我们的ImageInfo结构,添加到List列表(会同时维护All、Video、Image三个列表)中;遍历结束后,通过EventBus发送消息到主线程,然后调用RecyclerView的Adapter来添加数据更新界面。虽然将耗时任务放在了子线程,但是由于8000多条遍历及ImageInfo的创建,消耗了大量内存和时间。

现在分析下功能需求:我们的App是视频编辑类App,用户使用相册不会选择全部,或者说进入的时候不需要看到全部内容,所以只需要加载一屏的图片数据就好了,其他的没有显示的部分,等用户切换卡片或者下滑时候加载更多。换句话说,优化成recyclerview下拉加载更多样式。

先说下我优化后的结果:保证功能效果的同时,从点击功能点到显示列表,用时300多ms,和之前的4s左右相比,用户体验提升非常明显。

优化步骤:

1、将All、Video、Image三个Fragment改为懒加载模式,具体方法google一下。

2、将RecyclerView改为分段加载模式。

4ed077c16fbcc48add6b55134a670bec.png

3、分页请求数据。由于每次查询60条数据库时间都在几十毫秒,时间可以说是很及时,所以不对查询的结果及构建的ImageInfo列表进行存储,减少内存的长期占用。构造的查询字段,参数是文件夹名和修改时间(时间倒序排列),构建完ImageInfo数据后EventBus发送到指定Fragment页面进行页面更新处理。

b59b1f791d0db24ad3cfd6d13cb64bc3.png

7f22aa59d906f11f6331ca2b6d6fa0ce.png

4、预加载一定数量的RecyclerView子视图。这个页面,我们的设计是一排四个子视图,每个子视图都是正方形,那么一屏的子视图数就在(ScreenHeight/(ScreenWidth/4) + 2) * 4个(多创建一排,防止不够用)。其实一个布局文件inflate耗时也就35ms左右,但是顶不住数量多啊,我这个测试手机一次要建28个,那总时间就变成了35 * 28 = 980ms,加上其他时间的耗费,单个Fragment显示的用时在1s多,所以把大量子视图在子线程创建以免阻塞main线程非常有必要。

b8bb0441c5546ff6bd7d65614d50998e.png

使用的时候就简单判断下:

1ce6e1f1face1abde4cb15954acd393e.png

按以上方法到这里,你运行一下,其实就发现相册加载性能提升已经非常明显了,但是有个问题就是再次执行以上onCreateViewHolder时候会报异常:java.lang.IllegalStateException: ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)。看提示意思就是view已经有了一个parent了,再使用时候添加一个parent就会出错,因为view只能有一个直接parent视图。那解决方案就是清理一下view的parent,你搜一下会发现view中没有setParent的方法,有一个assignParent还是私有的,所以重置不了view的视图的parent,那就没法重复利用。好在突然想到view是在recyclerview中存在,在在fragment要销毁时候,RecyclerView可以清理一下所有子视图来达到重置view的parent的目的。看下RecyclerView的removeAllViewsInLayout源码:

public void removeAllViewsInLayout() {

for (int i = count - 1; i >= 0; i--) {final View view = children[i];

……

view.mParent = null; //重置view的parent。

……

}

……

}

好了,优化到此已经结束,希望你的相册进入时间也进入毫秒级。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值