【问题标题】:How to manage multiple download with Firebase and RecyclerView如何使用 Firebase 和 RecyclerView 管理多个下载
【发布时间】:2018-03-14 09:41:51
【问题描述】:

我有一个 RecyclerViewFirebaseRecyclerAdapter 与项目。每个项目都引用了Firebase 存储中的一些文件。每个项目都有下载按钮。我使用 storageReference.getFile(location) 从 firebase 存储下载文件。 当我点击下载按钮并等待下载完成时,选中的图标(绿色图标)在特定位置正确显示。

我的问题是当我同时下载多个项目时(当我点击多个项目时),绿色图标没有显示在每个项目的适当位置。

如何同时管理每个项目的多个下载,以便在特定项目下载完成后在特定位置显示绿色图标?

下载按钮后面OnBindViewHolder中的代码。

holder.imgDocumentChecker.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(final View view) {
        holder.imgDocumentChecker.setVisibility(View.GONE);
        holder.txtProgress.setVisibility(View.VISIBLE);
        holder.progressBar.setVisibility(View.VISIBLE);
        final Document item = getItem(holder.getAdapterPosition());
        final File parent = fileHelper.parentFolderGenerator(item);
        counter = 0;
        if (item.getFirebaseStorageFiles() != null && !item.getFirebaseStorageFiles().isEmpty()) {
            if (parent.listFiles() == null) {
                final String[] files = item.getFirebaseStorageFiles().split("____");
                if (files != null && files.length > 0) {
                    for (int i = 0; i < files.length; i++) {
                        String fileName = files[i].substring(files[i].lastIndexOf("/") + 1);
                        String storageFileUrl = Constants.ROOT_FIREBASE_STORAGE_URL + item.getDocFolder() + File.separator + files[i];
                        if (!parent.exists()) {
                            parent.mkdirs();
                        }

                        File localFile = new File(parent, fileName);
                        StorageReference storageReference = storage.getReferenceFromUrl(storageFileUrl);
                        storageReference.getFile(localFile)
                          .addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
                            @Override
                            public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
                                counter++;
                                int valeur = (100 / files.length) * counter;
                                holder.progressBar.setProgress(valeur);
                                holder.txtProgress.setText(valeur + "");
                                Log.d("progressvalues:",  "valeur:"+valeur+"|counter:"+counter+"|lengh:"+files.length);

                                if (counter == files.length) {
                                    holder.txtProgress.setVisibility(View.GONE);
                                    holder.progressBar.setVisibility(View.GONE);
                                    holder.imgDocumentChecker.setVisibility(View.VISIBLE);
                                    holder.imgDocumentChecker.setImageResource(R.drawable.done_ic);
                                }
                            }
                        }).addOnProgressListener(new OnProgressListener<FileDownloadTask.TaskSnapshot>() {
                            @Override
                            public void onProgress(FileDownloadTask.TaskSnapshot taskSnapshot) {
                                double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                holder.txtProgress.setVisibility(View.GONE);
                                holder.progressBar.setVisibility(View.GONE);
                            }
                        });
                    }
                }
            } else {
                startDocumentContentActivity(item, getRef(position));
            }
        }
    }
});

请帮忙。

【问题讨论】:

  • 你不应该在适配器中提出请求,因为这个视图可以被回收和虚拟处理。我建议您让另一个类处理请求,并在响应到来时通知适配器这些更改。
  • 感谢@JoaquimLey 的回答。即使我创建了一个单独的类来处理请求,我也需要在每个项目中发生单击时从OnBindViewHolder 调用这个类。你能解释一下你的建议吗?

标签: android firebase firebase-realtime-database android-recyclerview firebaseui


【解决方案1】:

就像 cmets 中提到的那样,这个请求不应该在 RecyclerView.Adapter 中完成,并且应该绝对不onBindViewHolder 中完成。

您应该将其抽象为一个单独的类,Presenter 或框架自己的ViewModel,也就是说:

一旦提出请求并收到新数据,您应该更新适配器的数据model 并通知这些更改。

报告一次点击(最终会触发一个请求)应该通过一个界面完成,您可以在其中拥有您的Adapter

public interface Listener {
  void onItemClicked(YourModelPojo item);
}

而您的 Activity/Fragment/Presenter 无论您想做什么抽象都会实现此 Listener 接口。

所以你的适配器的

holder.imgDocumentChecker.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(final View view) {
        // Update the UI the request is being made and report to listener
        listener.onItemClicked(data.get(getAdapterPosition()));
}

那么您的适配器也应该有一个关于适配器数据的更新项并通知此更改。由于您的模型更改了您的 bindViewHolder 将正确更新 UI。

当然,您必须实现这些 UI 更改(数据下载/更新/等)


我写了一些你可以依赖的文章(带有开源代码):

【讨论】:

  • 非常感谢。我会阅读您的教程并遵循您的建议。
  • 祝你好运,希望你能找到一个好的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-12
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多