如何在for循环内同步执行firebase功能?

时间:2018-04-26 04:31:18

标签: android firebase firebase-realtime-database

我正从for firebase数据库中检索for循环中的数据,但问题是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) {

                            }
                        });
    }

3 个答案:

答案 0 :(得分:2)

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

if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))内,您应该请求您的界面。

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

答案 1 :(得分:1)

这是我的解决方案:

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) {

        }
    });
}

答案 2 :(得分:1)

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

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代码,不要复制逐字哈哈。