You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

安卓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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 10:15:03