【问题标题】:How to execute firebase function synchronously inside for loop?如何在for循环内同步执行firebase函数?
【发布时间】:2018-04-26 04:31:18
【问题描述】:

我正在 for 循环中从 firebase 数据库中检索数据,但问题是 firebase 函数没有同步执行,我知道 firebase 函数是异步的。有什么解决办法吗?

代码:-

registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
        {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                peopleModelList.clear();

                for(DataSnapshot snapshot : dataSnapshot.getChildren())
                {
                    peopleModel = new PeopleModel();

                    peopleHashMap =(HashMap)snapshot.getValue();

                    peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
                    peopleModel.setNickname((String)peopleHashMap.get("nickname"));
                    peopleModel.setChatRoom(snapshot.getKey());

                    Log.d("kkkk","1st");

                    if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
                    {
                        registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
                                peopleModelList.add(peopleModel);
                                Log.d("kkkk","2nd");
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {

                            }
                        });
                    }
                    Log.d("kkkk","3rd");

                }
                iCallBackPeople.peopleAct(peopleModelList);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });

输出:-

1st
3rd
2nd

但我想要这样的输出

1st
2nd
3rd

注意:- 我搜索了,但没有任何解决方案!

How to get data from Firebase Database in a loop?

Firebase addListenerForSingleValueEvent excute later in loop

我试过了,但对我不起作用,它用最后一项填满了我的清单!

public void listOfUsers(final ICallBackPeople iCallBackPeople) {
        count=0;
        //peopleModelList = new ArrayList<>();
        sortedMap = new TreeMap<>();
       // peopleModelList = new ArrayList<PeopleModel>(sortedMap.values());
        registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
        {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
             //   peopleModelList.clear();

                for(DataSnapshot snapshot : dataSnapshot.getChildren())
                {
                    peopleModel = new PeopleModel();

                    peopleHashMap =(HashMap)snapshot.getValue();

                    peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
                    peopleModel.setNickname((String)peopleHashMap.get("nickname"));
                    peopleModel.setChatRoom(snapshot.getKey());

                    //Object chatRoom = snapshot.getKey();
                    Log.d("kkkk","1st");

                    if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
                    {

                        addItem(count,iCallBackPeople);
                        count++;
                    }
                    Log.d("kkkk","3rd");

                }
                Log.d("kkkk","end");
                //iCallBackPeople.peopleAct(peopleModelList);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
    }

    private void addItem(final int index, final ICallBackPeople iCallBackPeople) {
        registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
                Log.d("kkkk","2nd");
                sortedMap.put(index, peopleModel);
                // sortedMap will sort your list by key (in this case, key is integer)


                 if(sortedMap.size()==2)
                 {
                     peopleModelList = new ArrayList<PeopleModel>(sortedMap.values());
                     iCallBackPeople.peopleAct(peopleModelList);
                 }

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

我试过了,但没有得到所有项目,只获取快照中最后一个项目的列表

public void listOfUsers(final ICallBackPeople iCallBackPeople) {

        peopleModelList = new ArrayList<>();

        registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
        {
            PeopleModel peopleModel;
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                peopleModelList.clear();

                for(final DataSnapshot snapshot : dataSnapshot.getChildren())
                {
                    peopleModel = new PeopleModel();

                    peopleHashMap =(HashMap)snapshot.getValue();

                    peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
                    peopleModel.setNickname((String)peopleHashMap.get("nickname"));
                    peopleModel.setChatRoom(snapshot.getKey());


                    if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
                    {
                        getToken(new CallBackGetToken() {
                            @Override
                            public void token(String token) {
                                peopleModel.setRefresh_token(token);
                                Toast.makeText(context, token, Toast.LENGTH_SHORT).show();
                                peopleModelList.add(peopleModel);

                                //here i am checking my peopleModelList size is equal or not to snapshot
                                if(peopleModelList.size()==2)
                                    iCallBackPeople.peopleAct(peopleModelList);
                            }
                        },peopleModel);
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
    }

    private void getToken(final CallBackGetToken callBackGetToken ,PeopleModel peopleModel) {
        registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                callBackGetToken.token((String)dataSnapshot.child("refresh_token").getValue());
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {

                            }
                        });
    }

【问题讨论】:

  • 这并不意味着它不起作用。它有效,但它只显示最后一个对象的名称。为此,您应该将该语句从 for 循环中取出,因为每次迭代都会调用该语句,最终只有一项,最后一项,对吧?
  • 是的,假设我有一个模型,其中有 3 个成员,所以我在调用回调函数之前获得 2 个数据成员值,在回调函数之后获得 1 个数据成员值然后放入列表!
  • 请回复@。同样在这种情况下,您需要等待数据。

标签: android firebase firebase-realtime-database


【解决方案1】:

我认为您应该通过一个接口(创建一个并在此类上实现)。接口内的方法应该有一个字符串作为参数(它将接收您的 peopleModel.getChatWith() )。

在你的if(peopleModel.getChatWith()!=null &amp;&amp; !("".equals(peopleModel.getChatWith())))你应该请求你的接口。

我认为这是您异步问题的解决方案。

【讨论】:

  • 好吧,我会尝试使用 EventBus、多线程方法(使用 RX And​​roid),甚至是广播接收器,这三种方法之一肯定可以解决您的问题。
  • 谢谢!你能提供一些我可以学习或尝试的链接吗!
【解决方案2】:

这是我的解决方案:

int count =0;

SortedMap<Integer,PeopleModel> sortedMap;
private void set() {
     count =0;
    registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
    {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            peopleModelList.clear();
            sortedMap = new TreeMap<>();
            for(DataSnapshot snapshot : dataSnapshot.getChildren())
            {
                peopleModel = new PeopleModel();

                peopleHashMap =(HashMap)snapshot.getValue();

                peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
                peopleModel.setNickname((String)peopleHashMap.get("nickname"));
                peopleModel.setChatRoom(snapshot.getKey());

                Log.d("kkkk","1st");

                if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
                {
                    addItem(count);
                    count++;
                }
                Log.d("kkkk","3rd");

            }
            iCallBackPeople.peopleAct(peopleModelList);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });
}

private void addItem(final int index) {
    registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
            Log.d("kkkk","2nd");
            sortedMap.put(index, peopleModel);
            // sortedMap will sort your list by key (in this case, key is integer)
            // you can get peopleModelList = new ArrayList<>(sortedMap.values);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

【讨论】:

  • 我把 peopleModelList = new ArrayList(sortedMap.values());?
  • 你想在哪里获取 peopleModelList
  • 在我的情况下 sortedMap 总是只填充 peoplemodel 的最后一个对象!
【解决方案3】:

也许我过于简化了,但我觉得你应该只使用简单的递归。

List<People> peopleList;
int currentIndex = 0

private void myFirebaseMethodAction(person){
     registerListener.onCallbacks(new ValueListener(){
             onDataChanged(){
                  person.addStufforDoStuff();
                  if(peopleList.size > currentIndex + 1){
                      myFirebaseMethodAction(peopleList.get(++currentIndex)
                  }
             }
             onFailed(){
                  //handle it
             }
     }
}

这有意义吗? 只是说用索引遍历列表,很简单。 顺便说一句,上面是pseduo代码,不要逐字复制哈哈。

【讨论】:

  • 感谢您的支持,实际上直到现在我都无法解决这个问题,因为我错误地在我的实际代码中输入了一些错误的代码,所以结果是可以预期的,但现在当我看到错误时那里的代码然后我删除了错误的代码,现在我再次遇到这个问题我的列表没有得到更新。
  • 我不确定你现在在问什么?您的问题是如何同步您的列表步行以等待回调。我提供了那个解决方案。你现在问的是不同的东西吗?什么列表是空的?这不是你的问题的一部分,所以我不知道如何回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
  • 2022-10-21
相关资源
最近更新 更多