2

My problem is that I need to wait for the data from Firebase to be retrieved on the method "onDataChange" before ending my main method.

My code is (CalendarDbHelper) :

public synchronized ArrayList<Day> listDays()
    {
       final  CountDownLatch done = new CountDownLatch(1);
        db.addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if(dataSnapshot.exists())
                {
                    for(DataSnapshot postSnapShot:dataSnapshot.getChildren())
                    {
                        Day day=postSnapShot.getValue(Day.class);
                        listDays.add(day);

                    }
                }
               done.countDown();
            }


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

            }

        });

        try {
            done.await(); 
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        return listDays;

    }

As you can see, I'm already trying to wait with a CountDownLatch, but it doesn't work : it gets stuck.

I need the listDays for the activity "CalendarActivity" where I use it like this :

 //Real initialization of the database
        db = FirebaseDatabase.getInstance().getReference();
        mDatabase = new CalendarDbHelper(db);
        final List<Day> allDays = mDatabase.listDays();



        //Activating things to click on
        if(allDays.size() > 0){
            calendarRV.setVisibility(View.VISIBLE);
            calendarRVAdapter = new CalendarAdapter(this, allDays, new CalendarAdapter.OnListItemClickListener() {

                @Override
                public void onListItemClick(int clickedItemIndex) {
                    String id = allDays.get(clickedItemIndex).getId();
                    MyCustomAlertDialog(id);
                }
            });
            calendarRV.setAdapter(calendarRVAdapter);
        }else {
            calendarRV.setVisibility(View.GONE);
            Toast.makeText(this, "There is no product in the database. Start adding now", Toast.LENGTH_LONG).show();
        }
Fire-In-D-Hole
  • 270
  • 2
  • 13
Nouxy
  • 31
  • 7

2 Answers2

0

if this is your "main method",you should put the return data when the onDataChange is triggered

shadow
  • 114
  • 11
  • I don't really understand how I'm supposed to do that.. Do you want me to put a "return listDays" inside the onDataChange ? – Nouxy Apr 21 '19 at 18:29
  • @Nouxy is your "main method" call this function to get the data ??? – shadow Apr 21 '19 at 18:33
  • if it is,from main,call this method but dont return the data.Keep the view show progress.inside the onDatachange, do the function to update the UI when the data is returned.and if you want to do it just 1 time,clear the datachange listener – shadow Apr 21 '19 at 18:34
  • I'm sorry, what do you mean by "main method" ? I don't really understand what you're telling me to do – Nouxy Apr 21 '19 at 18:50
  • private OnGetDataDone onDone; CalendarDbHelper(db,OnGetDataDone onDone){ this.onDone = onDone; } public interface OnGetDataDone{ void onDone(ListDay listday) } add this to your CalendarDbHelper and put all the code which update ui in onDone method override in your CalendarActivity – shadow Apr 22 '19 at 03:03
0

Try this.

 public synchronized ArrayList<Day> listDays()
    {
   final  CountDownLatch done = new CountDownLatch(1);
    db.addValueEventListener(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) 
{
            if(dataSnapshot.exists())
            {
                for(DataSnapshot postSnapShot:dataSnapshot.getChildren())
                {
                    Day day=postSnapShot.getValue(Day.class);
                    listDays.add(day);

                }

             // Do whatever you want to do with your list from here..

            }
           done.countDown();
        }


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

        }

    });

    try {
        done.await(); 
    } catch(InterruptedException e) {
        e.printStackTrace();
    }
    return listDays;

}
Gulshan Yadav
  • 424
  • 5
  • 13
  • It doesn't work since the Day created inside the "for" loop isn't recognized on the line "listDays.add(day);" that is outside the "for" loop :/ – Nouxy Apr 21 '19 at 18:32
  • So the final solution is the updated answer. I was stuck in this situation too, some days ago. I tried this way to work. And everything works perfectly. – Gulshan Yadav Apr 21 '19 at 18:40
  • Can I see your full code?? Where you are using that listDays in the code?? – Gulshan Yadav Apr 21 '19 at 18:42
  • I just uploaded an edit of where I'm using listDays in my code :) – Nouxy Apr 21 '19 at 18:48