在ViewHolder中使用RxJava

时间:2018-12-13 21:15:10

标签: java android android-recyclerview rx-java android-viewholder

我致力于图像编辑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的bind方法中绑定到此可观察对象的方式:

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发出下载进度和对象ID,在我的活动中进行订阅并在适配器中找到要更新的项目,然后根据进度进行更新?

编辑

updateDownloadProgress方法:

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

1 个答案:

答案 0 :(得分:0)

您可以使用setTag和getTag,以便仅更新当前的ViewHolder