1

I have a block of code that gets called before another block of code. I want the first block of code to execute entirely before the other code gets called as it is null otherwise. The code is shown below

public void displayGraph1() {
        xnumsList = new ArrayList<>();
        namesList = new ArrayList<>();
        xxx = new ArrayList<>();
        DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("child");
        ref.addValueEventListener(new ValueEventListener() {
            @Override
            public synchronized void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot child : dataSnapshot.getChildren()) {
                    key = child.getKey();
                    DatabaseReference checkingWhoisInWhatChild = FirebaseDatabase.getInstance().getReference().child("child").child(key);
                    checkingWhoisInWhatClass.addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            String module = dataSnapshot.child("a").getValue().toString();
                            String xnum = dataSnapshot.child("b").getValue().toString();
                            for (int i = 0; i < arrayOfModules.size(); i++) {

                                String lecturerModule = arrayOfModules.get(i);
                                if (module.equals(lecturerModule)) {
                                    xxx.add(xnum);
                                }
                            }                          
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {

                        }
                    });
                }                
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
        //null array
        for (int i = 0; i < xxx.size(); i++) {
            Log.d("dddd", "arraycontents" + xxx.get(i));
        }

Obviously this is not the whole method but my point is that the loop at the bottom gets called before the preceding code due to asynchronous calls. I want a way to make sure that the code above is executed first so that the size of the array in the loop is not null. I have debugged the code and the array is not empty / null normally so I'm 100% sure that this is an asynchronous call that is causing the issue of the empty array in the loop. I'm looking for a way to synchronize the code, I have tried using the keyword "synchronized" on the functions and I have even tried to make a single thread for the entire function but this hasn't proven to work for me. Any help is appreciated. Thank you

RonanD1807
  • 55
  • 1
  • 7
  • 2
    It is, in fact, the result of `addValueEventListener` being an asynchronous call. You sholdn't try to do anything to change that fact - *never block the main thread* - just make sure that your loop only executes after the callback is invoked by putting the code inside the callback, or using one of the usual methods of async programming. – Doug Stevenson Feb 26 '20 at 21:42
  • I have tried this but i still get the same issue. It is because I have nested for loops which are needed for this code block – RonanD1807 Feb 26 '20 at 21:57
  • Your for loops make things a little tricky. You could try checking a counter variable within your callback to keep track of when all of the callbacks have been processed. Then, you can execute the rest of your code once they've all returned. – Sammy T Feb 27 '20 at 02:14
  • Check **[this](https://stackoverflow.com/questions/47847694/how-to-return-datasnapshot-value-as-a-result-of-a-method/47853774)** out. – Alex Mamo Feb 27 '20 at 11:13

0 Answers0