当我在 Android 中将文件上传到 Firebase 存储时,进度条不更新
Progress Bar Not Updating When I Upload Files To Firebase Storage in Android
让我解释一下整个场景,我想将文件上传到 Firebase,所以我做了一个布局,其中有一个用于 Selecting 文件的按钮、一个滚动视图和一个回收视图,无论我 Select 来自我设备的什么文件,它都会显示在回收站视图上并开始上传。这是我的按钮代码及其上传方式。这是在文件 UploadActivity.java
中
当用户 Select 多个文件时,if 条件将为真,当用户 Select 单个文件时,将执行 else 部分。 (这是有问题的地方)
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();
}
});
这是更新此 UploadActivity 中的进度条值的数组列表。
ArrayList<Integer> progressValue;
所有这些值都将在 RecyclerView 适配器中更改,以反映 UploadActivity 中存在的 RecyclerView 的更改。 (仅供参考)
@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();
}
注意:当我第一次 Select 文件时,它不会产生任何问题它显示适当的增加进度条并在上传完成时检查图标..但是如果我再次 Select 文件然后文件已成功上传,但进度条不工作,甚至复选标记(我在上传完成时设置复选标记图标)也不显示。但是,如果当我返回并单击上传按钮时 UploadActivity 再次启动,那么它再次运行完美。
这可能对您有帮助,也可能没有帮助,但重构您的适配器以适应 1 个且仅 1 个数据列表。您目前似乎正在调整 3 个列表,这使您的逻辑更加复杂。您有文件、进度和状态列表。
这是一个示例模型,应该代表您正在调整的内容。
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;}
}
在您的适配器中,您想使用差异回调来区分新旧项目。
这是简单的差异回调
https://medium.com/android-news/smart-way-to-update-recyclerview-using-diffutil-345941a160e0
在你的进度监听器中
@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);
}
让我解释一下整个场景,我想将文件上传到 Firebase,所以我做了一个布局,其中有一个用于 Selecting 文件的按钮、一个滚动视图和一个回收视图,无论我 Select 来自我设备的什么文件,它都会显示在回收站视图上并开始上传。这是我的按钮代码及其上传方式。这是在文件 UploadActivity.java
中当用户 Select 多个文件时,if 条件将为真,当用户 Select 单个文件时,将执行 else 部分。 (这是有问题的地方)
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();
}
});
这是更新此 UploadActivity 中的进度条值的数组列表。
ArrayList<Integer> progressValue;
所有这些值都将在 RecyclerView 适配器中更改,以反映 UploadActivity 中存在的 RecyclerView 的更改。 (仅供参考)
@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();
}
注意:当我第一次 Select 文件时,它不会产生任何问题它显示适当的增加进度条并在上传完成时检查图标..但是如果我再次 Select 文件然后文件已成功上传,但进度条不工作,甚至复选标记(我在上传完成时设置复选标记图标)也不显示。但是,如果当我返回并单击上传按钮时 UploadActivity 再次启动,那么它再次运行完美。
这可能对您有帮助,也可能没有帮助,但重构您的适配器以适应 1 个且仅 1 个数据列表。您目前似乎正在调整 3 个列表,这使您的逻辑更加复杂。您有文件、进度和状态列表。
这是一个示例模型,应该代表您正在调整的内容。
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;}
}
在您的适配器中,您想使用差异回调来区分新旧项目。 这是简单的差异回调 https://medium.com/android-news/smart-way-to-update-recyclerview-using-diffutil-345941a160e0
在你的进度监听器中
@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);
}