0

I made this code below and I have problem with filling database. I want to download data from my database but somehow filling them is after fragment is choosen. Like firebase doesnt respect line by line behaviour.

Here fragment of code:

              Playlist x = new Playlist (0,"0","1988", true);
                x.setTitle("Spokojnie");
                x.setDescription("Kult");


                mAuth = FirebaseAuth.getInstance();
                database = FirebaseDatabase.getInstance();
                database_ref = database.getReference();
                final String[] album_array = new String[1];
                final String[] author_array = new String[1];
                ArrayList<Song> songs = new ArrayList<>();

                    if (mAuth.getCurrentUser() != null) {

                        database_ref.child("music").child("albums").child("Kult").child("Spokojnie").child("songs").addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(@NonNull DataSnapshot snapshot) {
                                album_array[0] = snapshot.getRef().getParent().getKey();
                                author_array[0] = snapshot.getRef().getParent().getParent().getKey();

                                 for (DataSnapshot ds: snapshot.getChildren()){
                                     System.out.println(ds.getKey().toString());
                                     Song local_song = new Song(0, author_array[0], album_array[0], ds.getKey().toString(),Uri.parse(ds.getValue().toString()));
                                    songs.add(local_song);
                                 }


                                x.setSongs(songs);


                                x.setImage_id(snapshot.child("image_id").getValue().toString());

                            }

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

                            }
                        });


                    }

                selectedFragment = new CurrentPlaylistFragment(x);

Here my architecture on firebase side:

enter image description here

fariji1294
  • 41
  • 8
  • This is the expected behavior, because data is loaded asynchronously. If you run the code in a debugger and set breakpoints, you'll note that `selectedFragment = new CurrentPlaylistFragment(x)` is executed before `x.setSongs(songs)`. See https://stackoverflow.com/questions/50434836/getcontactsfromfirebase-method-return-an-empty-list/50435519#50435519 for more on this – Frank van Puffelen Jul 17 '21 at 20:07

1 Answers1

0

Try do something like this:

Playlist x = new Playlist (0,"0","1988", true);
x.setTitle("Spokojnie");
x.setDescription("Kult");


mAuth = FirebaseAuth.getInstance();
database = FirebaseDatabase.getInstance();
database_ref = database.getReference();
final String[] album_array = new String[1];
final String[] author_array = new String[1];
ArrayList<Song> songs = new ArrayList<>();

if (mAuth.getCurrentUser() != null) {

    database_ref.child("music").child("albums").child("Kult").child("Spokojnie").child("songs").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            album_array[0] = snapshot.getRef().getParent().getKey();
            author_array[0] = snapshot.getRef().getParent().getParent().getKey();

             for (DataSnapshot ds: snapshot.getChildren()){
                 System.out.println(ds.getKey().toString());
                 Song local_song = new Song(0, author_array[0], album_array[0], ds.getKey().toString(),Uri.parse(ds.getValue().toString()));
                songs.add(local_song);
             }


            x.setSongs(songs);


            x.setImage_id(snapshot.child("image_id").getValue().toString());
            afterRead(x);
        }

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

        }
    });


} else {
    afterRead(x);
}




public void afterRead(Playlist x) {
    CurrentPlaylistFragment selectedFragment = new CurrentPlaylistFragment(x);
    //TODO
}

Another solution can be the folowing:

Playlist x = new Playlist (0,"0","1988", true);
x.setTitle("Spokojnie");
x.setDescription("Kult");


mAuth = FirebaseAuth.getInstance();
database = FirebaseDatabase.getInstance();
database_ref = database.getReference();
final String[] album_array = new String[1];
final String[] author_array = new String[1];
ArrayList<Song> songs = new ArrayList<>();

if (mAuth.getCurrentUser() != null) {

    CountDownLatch conditionLatch = new CountDownLatch(1);
    database_ref.child("music").child("albums").child("Kult").child("Spokojnie").child("songs").addListenerForSingleValueEvent(new ValueEventListener() {

        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            album_array[0] = snapshot.getRef().getParent().getKey();
            author_array[0] = snapshot.getRef().getParent().getParent().getKey();

             for (DataSnapshot ds: snapshot.getChildren()){
                 System.out.println(ds.getKey().toString());
                 Song local_song = new Song(0, author_array[0], album_array[0], ds.getKey().toString(),Uri.parse(ds.getValue().toString()));
                songs.add(local_song);
             }


            x.setSongs(songs);


            x.setImage_id(snapshot.child("image_id").getValue().toString());
            conditionLatch.countDown();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            conditionLatch.countDown();
        }
    });
    conditionLatch.await();
}
selectedFragment = new CurrentPlaylistFragment(x);

The code in ValueEventListener runs with delay, because reading from firebase will take some time, you don't want to stop your program from running just because you need to read one value.

Ofek
  • 1,065
  • 6
  • 19