«Слишком много открытых файлов» при прокрутке RecyclerView - PullRequest
0 голосов
/ 04 октября 2018

У меня есть приложение, которое выполняет множество асинхронных вызовов внешних 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, чтобы освободить файл (ы)?

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Вам следует отменить вызовы API и другие асинхронные операции, когда элемент не отображается на экране.Потому что, если пользователь прокручивает быстро, у вас будут запущены сотни бесполезных задач.

Итак, просто отмените свои задачи, когда прокручивается представление.

Вы можете выполнить всю эту работу в методе RecylerView void onViewRecycled (VH holder)..

Из документации:

void onViewRecycled (VH holder)

Вызывается, когда представление, созданное этим адаптером, было переработано.

Представление переработанокогда RecyclerView.LayoutManager решает, что его больше не нужно подключать к его родительскому RecyclerView.Это может быть связано с тем, что он вышел из-под контроля или набор кэшированных представлений, представленных представлениями, все еще прикрепленными к родительскому RecyclerView.Если к представлению элемента привязаны большие или дорогие данные, такие как большие растровые изображения, это может быть хорошим местом для освобождения этих ресурсов.

RecyclerView вызывает этот метод непосредственно перед очисткой внутренних данных ViewHolder и отправкой его в RecycledViewPool.Таким образом, если ViewHolder содержал действительную информацию до повторного использования, вы можете вызвать getAdapterPosition (), чтобы получить позицию адаптера.

0 голосов
/ 04 октября 2018

Я считаю, что все, что вам нужно сделать, это закрыть ваши соединения / сокеты после загрузки файла:

Сокет принимает - "Слишком много открытых файлов"

Есливы кешируете загруженные образы, вы также должны правильно закрыть FileInputStream или FileOutputStream

Также отмените регистрацию вашего адаптера, пока уничтожается корневой вид:

@Override
protected void onDestroy() {
    super.onDestroy();
    recyclerView.setAdapter(null);
}
...