Search code examples
androidfirebaseandroid-recyclerviewfirebase-storageandroid-progressbar

Progress Bar Not Updating When I Upload Files To Firebase Storage in Android


Let Me Explain The Whole Scenario, I Wanted To Upload Files To Firebase So That I've Made One Layout In Which I've A Button For Selecting Files, A Scrollview And A Recycler View, Whatever File I Select From My Device It Shows On Recycler View And Start Uploading. This is The Code Of My Button And How It's Uploading. This is In File UploadActivity.java

When User Select Multiple Files The If Condition Will Be True And When User Select Single File The Else Part Will Be Executed. (THIS IS THE PROBLEMATIC AREA)

ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
            Intent intentReceived = result.getData();
            ClipData clipData = result.getData().getClipData();
            if (clipData != null) {
                for (int i = 0; i < intentReceived.getClipData().getItemCount(); i++) {
                    Uri fileUri = intentReceived.getClipData().getItemAt(i).getUri();
                    String fileName = UploadActivity.this.getFileNameFromUri(fileUri);
                    uploadFiles.add(fileName);
                    uploadStatus.add("Loading");
                    adapter.notifyDataSetChanged();

                    final int index = i;

                    //Uploading File To Firebase Storage
                    StorageReference uploader = storageReference.child("/" + Path).child(fileName);
                    uploader.putFile(fileUri)
                            .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                                @Override
                                public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) {
                                    try{
                                        progressValue.remove(index);
                                    }catch(Exception e){
                                        //Do Nothing
                                    }
                                    double progress = (100.0 * snapshot.getBytesTransferred()) / snapshot.getTotalByteCount();
                                    int currentProgress = (int) progress;
                                    Integer passProgress = Integer.valueOf(currentProgress);
                                    try{
                                        progressValue.add(index,passProgress);
                                    }catch (Exception e){
                                        progressValue.add(passProgress);
                                    }
                                    uploadStatus.remove(index);
                                    uploadStatus.add(index, "Processing");
                                    adapter.notifyDataSetChanged();
                                }
                            });

Here Is The Array List To Update Progress Bar Value in This UploadActivity.

ArrayList<Integer> progressValue;

All These Values Are Going To Be Changed In RecyclerView Adapter To Reflect Changes in The RecyclerView Exist In UploadActivity. (THIS IS JUST FOR REFERENCE)

@Override
public void onBindViewHolder(@NonNull uploadViewHolder holder, int position) {
    String fileName = files.get(position);
    if(fileName.length() > 25)
        fileName = fileName.substring(0,25)+"...";
    holder.uploadFileName.setText(fileName);

    String fileStatus = status.get(position);
    if(fileStatus.equals("Processing")){
        int updateProgress = progress.get(position).intValue();
        holder.uploadProgressBar.setProgress(updateProgress);
    }
    if(fileStatus.equals("Done")){
        holder.uploadProgressBar.setProgress(0);
        holder.uploadProgressBar.setVisibility(View.GONE);
        holder.uploadComplete.setImageResource(R.drawable.check_circle);
    }
}

@Override
public int getItemCount() {
    return files.size();
}

Note : When I First Time Select Files It Doesn't Create Any Issue It Shows Proper Increasing Progress Bar And Check icon When Uploading is Done.. But If I Select Files Again Then Files Are Successfully Uploading But Progressbar is Not Working And Even Check Mark (I Set A Check Mark Icon When Uploading is Done) is Also Not Showing. But If UploadActivity Starts Again When I Go Back And Click On Upload Button Then Again It Works Perfect.


Solution

  • This may help you or may not but refactor you adapter to adapt 1 and only 1 list of data. You currently seem to be adapting 3 lists which makes your logic more complicated. You have Lists of Files, progresses, and statuses.

    Here is an example model that should represent what you are adapting.

    public class FileModel {
       private String name;
       private int progress = 0;
       private String status = "Loading";
    
       public FileModel(String name){
          this.name = name;
       }
       public String getName(){return name;}
       public int getProgress() {return progress;}
       public String getStatus() {return status;}
       public void setProgress(int progress) {this.progress = progress;}
       public void setStatus(String status) {this.status = status;}
    }
    

    Inside your adapter you want to use a diff callback to tell the difference between old and new items. Here is simple diff callback https://medium.com/android-news/smart-way-to-update-recyclerview-using-diffutil-345941a160e0

    And in you progress listener

    @Override
    public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) {
        double progress = (100.0 * snapshot.getBytesTransferred()) / snapshot.getTotalByteCount();
        //The model pertaining to this file.
        fileModel.setProgress((int) progress);
        //create a new function in your adapter to re-set the list
        //with the new changes.
        //don't worry its very fast with diff callback
        adapter.setList(fileModels);
    }