Использование RxJava внутри ViewHolder - PullRequest
0 голосов
/ 14 декабря 2018

Я работаю над приложением для редактирования изображений Android.В этом приложении пользователи могут загружать ресурсы.Поскольку эти ресурсы имеют большой размер, я использую DownloadManager для их загрузки.Элементы, которые пользователи могут загрузить, отображаются в RecyclerView.Я хочу связать задачи загрузки DownloadManager с элементами в RecyclerView, чтобы пользователь мог видеть ход загрузки.Вот оболочка Rx, которую я написал для получения прогресса загрузки.

private Observable<Integer> createDownloadProgressListener(long downloadId) {
    return Observable.create(observer -> {
        boolean downloading = true;

        while (downloading) {
            DownloadManager.Query q = new DownloadManager.Query();
            q.setFilterById(downloadId);

            Cursor cursor = downloadManager.query(q);
            cursor.moveToFirst();
            int bytes_downloaded = cursor.getInt(cursor
                    .getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
            int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));

            if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                downloading = false;
                observer.onNext(100);
                observer.onCompleted();
            }

            final int dlProgress = (int) ((bytes_downloaded * 100L) / bytes_total);

            observer.onNext(dlProgress);
            Log.d(TAG, "Download progress: " + dlProgress);

            cursor.close();
        }
    });
}

Вот как я привязываюсь к этому наблюдаемому в методе привязки моего ViewHolder:

private void bindEffectDownloadTask() {
        if (item.getDownloadRefId() != null && baseActivity.rxDownloadManager.getDownloadProgressListener(item.getDownloadRefId()) != null) {  baseActivity.rxDownloadManager.getDownloadProgressListener(item.getDownloadRefId())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .doOnSubscribe(() -> item.setDownloading(true))
                    .doOnTerminate(() -> item.setDownloading(false))
                    .subscribe(progress ->
                        updateDownloadProgress(progress),
                    error -> {
                        Log.d(TAG, "Error in download task: " + error.getMessage());
                    },
                    () -> {
                        downloadedState();
                    });
        }
    }

Моя проблема в том, что updateDownloadProgress (где я устанавливаю прогресс пользовательского представления прогресса круга) обновляет не только текущий ViewHolder, но и другие.Как я могу убедиться, что обновлен только текущий ViewHolder?Или, если этот подход совершенно неправильный, каковы лучшие практики для работы с асинхронным потоком данных в элементах RecyclerView?Может быть, мне следует вывести прогресс загрузки и идентификатор объекта из объекта BehaviorSubject, подписаться на это в своей деятельности и найти элементы, которые будут обновлены в адаптере, и обновить их с прогрессом?

РЕДАКТИРОВАТЬ

метод updateDownloadProgress:

void updateDownloadProgress(int progress) {
  downloadButton.setVisibility(View.GONE);
  downloadProgressBar.setVisibility(View.VISIBLE);
  downloadProgressBar.setProgress(progress);
}

1 Ответ

0 голосов
/ 14 декабря 2018

Вы можете использовать setTag и getTag, чтобы обновлялся только текущий ViewHolder

...