java - Android 视图的弱引用安全吗?
问题描述
您好,我正在编写一个使用许多 customView(父级作为 FrameLayout 持有活动的上下文)的应用程序。
在应用程序中有一个 recyclerView,它的持有者拥有N
(大量)视图(自定义)。
由于视图的数量是动态添加的(我正在测试 10k+ 视图)。
在回收站视图中,我没有做任何特别的事情,而是使用协程,这样 10k 视图的渲染就不会阻塞Main Thread
但是由于每个 RecyclerView Holder 中有大量的 View,当我滚动并给出 OOM(内存不足)崩溃时,它会非常快地填满应用程序的堆内存。
为了解决这个问题,我阅读并发现我可以对 View 使用弱引用。但我没有找到任何示例或对这种方法的引用。所以我不确定在 Android View 上使用 WeakReference 是否是一个好的解决方案。
下面的代码和演示项目参考。
RecyclerView 适配器:
override fun onBindViewHolder(holder: ViewPageHolder, position: Int) {
val slideViewMultipleCanvas = SlideViewMultipleCanvas(context)
holder.slideViewItemHolder.addView(slideViewMultipleCanvas)
holder.positionHolder = position
val childJob = launch {
//this is where 10k+ view's are created
slideViewMultipleCanvas.setNumOfObjects(numOfItemsInViewPage)
slideViewMultipleCanvas.startJob()
}
map[position] = childJob
}
自定义视图:
...
...
suspend fun setNumOfObjects(numberOfObjects: Int) {
withContext(Dispatchers.Default) {
for (i in 0 until numberOfObjects) {
// To solve OOM as number of view here in heap are >10k
listOfObject.add(WeakReference(ShapeView(context)))
}
}
}
...
...
private fun addViewInScope(): Boolean {
for (shapeView in listOfObject) {
shapeView.get()?.let {
addView(it)
}
}
return true
}
....
....
在我的测试中使用 WeakReference 之后,我到目前为止还没有遇到任何问题( ),但我仍然会在启动并收集所有弱引用NO OOM's
时得到 Lag 。GC(Garbage Collector)
我主要担心的是
- 有没有其他方法可以在不使用 WeakReference 的情况下处理大量视图的创建?
- 如果我对视图使用弱引用,会有什么问题吗?
- 如何减少 GC 延迟?(即使使用 WeakReference 我也没有平滑滚动)
PS:我已经在处理:
- 如果 GC 收集的是弱引用的视图,则为 null 情况
- 在 RecyclerView 中回收视图时取消协程作业。(我也可以释放这个 ViewHolder 的弱引用视图吗???)
解决方案
查看 RecyclerViewPools,您应该能够使用 itemType 分配特定视图(如果动态创建的视图是相同的视图)并让 recyclerView 也重用这些视图
主要延迟不是来自弱引用,而是纯粹需要如此快速地生成这么多视图,如果您可以保留一个缓存的视图列表以供重用(有点像 recyclerViewPool),那么这将减少膨胀延迟
只有当你有这么多导致OOM的视图时才会出现问题,是否可以将视图组合成具有多种功能的通用视图(更少的物理视图,但每个视图都有更多的逻辑和复杂性,以适应在多种情况下使用
这将允许您多次重用相同的视图,这意味着更少的缓存/膨胀,您只需要确保代码有效地执行
推荐阅读
- python - 使用 pandas 将字典数据复制到 csv
- c - 带有结构指针的共享内存互斥锁
- javascript - drawImage 不在画布上渲染图像
- python - QTreeView 函数 rootIsDecorated 不起作用
- php - [php]如何只获取里面的文本
并将其构建为数组 - sql-server - 如何从两个不同的“发件人”地址发送 SSRS 报告?
- javascript - Google Chrome 版本 71.0.3573.0 上的“onChange”问题
- c# - Mysql 实体框架 Visual Studio 2017
- excel - 将 Excel 工作表导出为 pdf
- react-native - Expo Fingerprint API 在 Android 设备中无法正常工作。