如何使用Firebase和RecyclerView管理多个下载 [英] How to manage multiple download with Firebase and RecyclerView

查看:46
本文介绍了如何使用Firebase和RecyclerView管理多个下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a RecyclerView and FirebaseRecyclerAdapter with items. Each item has reference to some files in Firebase storage. each item has download button. I use storageReference.getFile(location) to download files from firebase storage. When I click on download button and wait for the download to finish, the checked icon (green icon) is showing correctly at specific position.

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

My problem is when I download multiple items at same time (when I click on multiple items), the green icon is not displays at appropriate position on every item.

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

How can I manage multiple download on every item simultaneously so that the green icon can be shown at specific position when specific item download finished?

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

The code in OnBindViewHolder behind the download button.

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));
            }
        }
    }
});

请帮助.

推荐答案

就像注释中提到的那样,不应在RecyclerView.Adapter中完成此请求,并且应该绝对不onBindViewHolder.

Like mentioned in the comments this request shouldn't be done in the RecyclerView.Adapter, and should definitely not be made in the onBindViewHolder.

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

You should abstract this to a separate class, a Presenter or the framework's own ViewModel, that being said:

发出请求并输入新数据后,您应该更新适配器的数据model并通知这些更改.

Once that request is made and the new data comes in, you should update your adapter's data model and notify of these changes.

报告点击(最终会触发请求)应该通过一个界面进行操作,您可以在该界面中放置Adapter:

Reporting a click (that would eventually trigger a request) should be done via an interface where you could have your Adapter:

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

您想要做的抽象的Activity/Fragment/Presenter都将实现此Listener接口.

And your Activity/Fragment/Presenter however abstract you want to do would implement this Listener interface.

所以您适配器的

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将正确更新用户界面.

Then your adapter should also have an update item on the adapter's data and notify of this change. Since your model changed your bindViewHolder would update the UI correctly.

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

Of course, you have to implement these UI changes (data downloading/updated/etc.)

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

I've written some articles that you can rely on (with open source code):

使用演示者-模型视图演示者

这篇关于如何使用Firebase和RecyclerView管理多个下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆