安卓Firestore开发如何等待OnSuccessListener执行完成后再运行后续代码
问题原因
这是异步回调的典型变量捕获问题:Firestore的get()请求是异步执行的,同步的for循环会先跑完所有迭代,将j[0]的值更新到r[0]之后,所有异步请求的OnSuccessListener才会陆续触发。此时所有回调访问的都是同一个j数组对象,拿到的自然都是最终的r[0]值。
解决方法
只需要在每次循环迭代中,把当前的j[0]值赋值给一个final的局部变量,让每个回调捕获自己对应迭代的固定值即可,修改后的代码如下:
public void display(RequestData rd[],int j) { Toast.makeText(Student_see_request_status.this,j+" h"+r[0]+"",Toast.LENGTH_SHORT).show(); //using current value of j } public void set() { FirebaseFirestore fs=FirebaseFirestore.getInstance(); DocumentReference doc=fs.collection("Request").document(FirebaseAuth.getInstance().getCurrentUser().getEmail()); doc.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() { @Override public void onSuccess(DocumentSnapshot documentSnapshot) { Map<String, Object> m = documentSnapshot.getData(); r[0] = (long) m.get("Request Number"); if(r[0]==0) { Toast.makeText(Student_see_request_status.this,"NO REQUESTS HERE",Toast.LENGTH_SHORT).show(); return; } rd=new RequestData[(int)r[0]+2]; for(int j[]={1};j[0]<=r[0];j[0]++) { // 新增该行,保存当前迭代的j值为final局部变量 final int currentJ = j[0]; doc.collection("Request " + currentJ).document("Request").get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() { @Override public void onSuccess(DocumentSnapshot documentSnapshot) { Map<String, Object> details = documentSnapshot.getData(); // 所有原使用j[0]的位置替换为currentJ rd[currentJ]=new RequestData(); rd[currentJ].setHeader("Change " + details.get("Change what") + " to " + details.get("Value")); rd[currentJ].setReason((String) details.get("Reason")); display(rd,currentJ); } }); } } }); }
原理说明
Java的匿名内部类捕获局部变量时,会把变量的副本存在自己的内部结构中,只有当变量是final(或者实际不可修改)时,这个副本的值才会和定义时的值保持一致,不会随外部变量更新而变化。我们每次循环都定义一个独立的currentJ变量,每个回调捕获的都是对应迭代的独立副本,自然就能拿到正确的索引值。
内容的提问来源于stack exchange,提问作者Vanshika
相关产品推荐
相关产品推荐

