首页 > 解决方案 > 滚动 RecyclerView 时出现“打开的文件太多”

问题描述

我有一个应用程序,它对外部 API 进行许多异步调用,以获取有关图像缩略图的详细信息,以便在用户滚动浏览它时加载到我的 RecyclerView(使用 Glide)中。Recyclerview 是“永无止境的”,因为如果用户想要滚动足够长的时间,可以加载数千张图像。

滚动浏览可能一百张图片后,我收到以下错误:

W/Adreno-GSL: <gsl_ldd_control:541>:ioctl fd 55 code 0xc0200933 (IOCTL_KGSL_TIMESTAMP_EVENT) failed: errno 24 Too many open files
  <ioctl_kgsl_syncobj_create:3977>: (38, 1f, 3907) fail 24 Too many open files
E/Parcel: fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 0, fds[i] is -1, fd_count is 1, error: Too many open files
I/Adreno: DequeueBuffer: dequeueBuffer failed
E/NativeCrypto: AppData::create pipe(2) failed: Too many open files

该应用程序永远不会崩溃,但它会保持冻结状态,直到我(等一下?然后)从应用程序中退出并重新进入它。

从我所做的研究中,我了解到一次可以打开多少个文件是有限制的,但我不确定如何控制它。

  1. 我如何知道当前打开了多少文件?
  2. 如何在等待更多文件释放时“暂停”我的 RecyclerView?
  3. 我应该在我的 AsyncTask 中做些什么来释放文件吗?

标签: androidandroid-recyclerviewandroid-asynctask

解决方案


当项目在屏幕上不可见时,您应该取消您的 api 调用和其他异步工作。因为如果用户快速滚动,您将运行数百个无用的任务。

因此,只需在滚动视图时取消您的任务。

您可以在 RecylerView 的void onViewRecycled (VH holder)方法中完成所有这些工作。

从文档:

void onViewRecycled (VH holder)

当此适配器创建的视图被回收时调用。

当 RecyclerView.LayoutManager 决定不再需要将视图附加到其父 RecyclerView 时,视图将被回收。这可能是因为它已失去可见性,或者由仍附加到父 RecyclerView 的视图表示的一组缓存视图。如果项目视图绑定了大型或昂贵的数据,例如大型位图,那么这可能是释放这些资源的好地方。

RecyclerView 在清除 ViewHolder 的内部数据并将其发送到 RecycledViewPool 之前调用此方法。这样,如果 ViewHolder 在被回收之前持有有效信息,您可以调用 getAdapterPosition() 来获取其适配器位置。


推荐阅读