只有当 ArrayList 到达它的最后一个元素时,如何执行代码?
Posted
技术标签:
【中文标题】只有当 ArrayList 到达它的最后一个元素时,如何执行代码?【英文标题】:How to execute code only when the ArrayList has reached it's last element? 【发布时间】:2018-03-13 14:49:47 【问题描述】:我正在运行一个 for 循环并将数据保存在其中的 firebase 上。
这是我的代码:
private int counter = 1;
pProgress.setMessage("Posting...");
pProgress.show();
pProgress.setCancelable(false);
for (int i=0; i<imageArray.size(); i++)
Uri file = Uri.fromFile(new File(imageArray.get(i).toString()));
String key = database.getReference().push().getKey();
UploadTask uploadTask = storage.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(key).child("product_image").putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener()
@Override
public void onFailure(@NonNull Exception exception)
// Handle unsuccessful uploads
).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>()
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot)
counter++;
if (counter == imageArray.size())
Toast.makeText(getBaseContext(), "successfully posted!", Toast.LENGTH_SHORT).show();
imageView.setImageResource(0);
pDescription.setText("");
pDuration.setText("");
pPrice.setText("");
label.setText("Label");
if (pProgress.isShowing())
pProgress.dismiss();
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
@SuppressWarnings("VisibleForTests")
Uri downloadUrl = taskSnapshot.getDownloadUrl();
imageUrls.add(downloadUrl.toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDescription").setValue(pDescription.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDuration").setValue(pDuration.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pPrice").setValue(pPrice.getText().toString());
if (imageUrls != null)
for (int i=0; i<imageUrls.size(); i++)
Log.d("imageUrlsSize", String.valueOf(imageUrls.size()));
String idtwo = database.getReference().push().getKey();
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child(idtwo).child("imageUrl").setValue(downloadUrl.toString());
if (imageUrls.size() > 0)
imageUrls.clear();
);
我想显示ProgressDialog
并在数据成功上传后将其关闭。同样,我也想清除EditText
字段和ImageView
。
我怎样才能知道imageArray
已经结束,以便我可以关闭 ProgressDialog 并清除 edittext 以及 imageview?
请告诉我。
【问题讨论】:
【参考方案1】:一种方法是检查回调中的计数。您可以在onFailure
和onSuccess
中检查它。像这样的
for (int i = 0; i < imageArray.size(); i++)
final int currentCount = i + 1;
/** code **/
onSuccess()
if (currentCount == imageArray.size()) // do something
您可能还需要将imageArray
声明为final。这样做的缺点是您将知道最后一个元素已被处理,但您将不知道是否还有其他请求仍在等待处理。更好的方法是在您的类中使用成员字段,例如
class YourClass private int currentCount = 0;
你会在你的回调中再次计算这个,例如
for (int i = 0; i < imageArray.size(); i++)
onSuccess()
currentCount++;
if (currentCount == imageArray.size()) // do something
【讨论】:
这两种方法都不起作用。当我将代码放入其中时,它会清空编辑文本,并且空字符串会保存在 firebase 上。 @HammadNasir 你做了什么?你能用新代码编辑你的帖子吗? @HammadNasir 将计数器更改为0
并在 onFailure
回调中增加它。【参考方案2】:
作为一个实时数据库,没有任何时候我们可以说我们已经从数据库中加载了所有的 reconar,或者 ArrayList 已经到达了它的最后一个元素。发生这种情况是因为每时每刻都有可能发生变化,即可以添加或删除一个/多个项目。这就是 Firebase 的构建方式。
但是对您的问题的简短回答,首先将 imageUrls
ArrayList 的声明移到 onSuccess()
方法中,否则由于此方法的异步行为,它将为空。其次,在您的类中定义一个名为 count
的变量,并在每次调用 onSuccess()
方法时增加它的值,并将其与列表中的 size
进行比较,如下所示:
int count = 0;
onSuccess()
count++;
if(count == imageArray.size() : do somethig ? do something else)
【讨论】:
【参考方案3】:您正在处理异步任务,因此您需要封装您的工作并使用队列和回调。试试这样的:
class Job
private Runnable completeCallback;
private String key;
private Uri file;
public Job(String key, Uri file)
this.key = key;
this.file = file;
public void setCompleteCallback(Runnable completeCallback)
this.completeCallback = completeCallback;
void doWork()
UploadTask uploadTask = storage.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(key).child("product_image").putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener()
@Override
public void onFailure(@NonNull Exception exception)
// Handle unsuccessful uploads
completeCallback.run();
).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>()
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot)
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
@SuppressWarnings("VisibleForTests")
Uri downloadUrl = taskSnapshot.getDownloadUrl();
imageUrls.add(downloadUrl.toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDescription").setValue(pDescription.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDuration").setValue(pDuration.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pPrice").setValue(pPrice.getText().toString());
if (imageUrls != null)
for (int i=0; i<imageUrls.size(); i++)
Log.d("imageUrlsSize", String.valueOf(imageUrls.size()));
String idtwo = database.getReference().push().getKey();
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child(idtwo).child("imageUrl").setValue(downloadUrl.toString());
if (imageUrls.size() > 0)
imageUrls.clear();
completeCallback.run();
);
class Queue
ArrayList<Job> jobs = new ArrayList<>();
private int total;
public void execute()
total = imageArray.size();
for (int i=0; i<imageArray.size(); i++)
Uri file = Uri.fromFile(new File(imageArray.get(i).toString()));
String key = database.getReference().push().getKey();
Job job = new Job(key, file);
job.setCompleteCallback(new Runnable()
@Override
public void run()
jobs.remove(job);
updateUi();
);
jobs.add(job);
for (int i = jobs.size() - 1; i >= 0; i--)
Job job = jobs.get(i);
job.doWork();
private void updateUi()
Log.d("UI", "Completed " + jobs.size() + "/" + total);
【讨论】:
【参考方案4】:我在Murat K的回答的帮助下想通了。
我只是转移了这段代码
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDescription").setValue(pDescription.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDuration").setValue(pDuration.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pPrice").setValue(pPrice.getText().toString());
退出for
循环,现在一切正常。
【讨论】:
以上是关于只有当 ArrayList 到达它的最后一个元素时,如何执行代码?的主要内容,如果未能解决你的问题,请参考以下文章