滚动 RecyclerView 时出现“打开的文件太多”
Posted
技术标签:
【中文标题】滚动 RecyclerView 时出现“打开的文件太多”【英文标题】:"Too many open files" when scrolling RecyclerView 【发布时间】:2019-03-10 07:40:07 【问题描述】:我有一个应用程序,它对外部 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
该应用永远不会崩溃,但它会一直冻结,直到我(稍等一下?然后)退出该应用并重新进入它。
根据我所做的研究,我了解到一次可以打开多少个文件是有限制的,但我不确定如何控制。
-
我如何知道当前打开了多少文件?
如何在 RecyclerView 等待更多文件释放时“暂停”它?
我应该在我的 AsyncTask 中做些什么来释放文件吗?
【问题讨论】:
你应该像 Picasso 或 glide 这样的库来抽象所有这些东西,而不是使用 asynctask 我正在使用 Glide,但我必须从 API 获取 URL 以提供给 Glide 以加载图像... 【参考方案1】:当项目在屏幕上不可见时,您应该取消您的 api 调用和其他异步工作。 因为如果用户快速滚动,您将有数百个无用的任务在运行。
所以,只需在视图滚动时取消您的任务。
您可以在 RecylerView 的 void onViewRecycled (VH holder)
方法中完成所有这些工作。
来自文档:
void onViewRecycled (VH holder)
在此适配器创建的视图被回收时调用。
当 RecyclerView.LayoutManager 决定回收视图时 不再需要附加到其父 RecyclerView。这可以是 因为它已经失去可见性或一组缓存视图 由仍附加到父 RecyclerView 的视图表示。如果 项目视图绑定了大或昂贵的数据,例如大 位图,这可能是释放这些资源的好地方。
RecyclerView 在清除 ViewHolder 之前调用此方法 内部数据并将其发送到 RecycledViewPool。这样,如果 ViewHolder 在被回收之前持有有效信息,你 可以调用 getAdapterPosition() 来获取它的适配器位置。
【讨论】:
【参考方案2】:我相信您所要做的就是在下载文件后关闭您的连接/套接字:
Socket accept - "Too many open files"
如果您正在缓存下载的图像,您还应该正确关闭您的FileInputStream
或FileOutputStream
同时在根视图被破坏时注销您的适配器:
@Override
protected void onDestroy()
super.onDestroy();
recyclerView.setAdapter(null);
【讨论】:
以上是关于滚动 RecyclerView 时出现“打开的文件太多”的主要内容,如果未能解决你的问题,请参考以下文章
在滚动 RecyclerView 时出现异常:-“java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item p
充气 RecyclerView 时出现 InflateException
实现 Recyclerview 过滤器时出现 indexoutofboundexception
Recyclerview部分:调用notifyDataSetChanged()时出现IllegalStateException [重复]