3

I am trying to retrieve data from Firebase realtime-database and put it on a CardView inside a RecyclerView inside a Fragment.

But the Fragment shown is blank white with no error. I retrieve the data inside OnCreate method and add it into a List.

While debugging the application, found out that even after assigning the retrieved data inside the onCreate method, the list is still NULL inside the onCreateView method.

Fragment Dashboard List Class:

public class fragment_dashboard_list extends Fragment {

    List<ibu> ibu_ibu;
    FirebaseDatabase database;
    DatabaseReference myRef ;
    String a;

    public fragment_dashboard_list() {}
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ibu_ibu = new ArrayList<>();

        database = FirebaseDatabase.getInstance();
        myRef = database.getReference("Guardian");

        myRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // This method is called once with the initial value and again
                // whenever data at this location is updated.

                for(DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){

                    ibu value = dataSnapshot1.getValue(ibu.class);
                    ibu ibu_val = new ibu();

                    String alamat = value.getAlamat();
                    String foto = value.getFoto();
                    String hp = value.getHp();
                    String ktp = value.getKtp();
                    String nama = value.getNama();
                    String privilege = value.getPrivilege();
                    String ttl = value.getTtl();

                    ibu_val.setAlamat(alamat);
                    ibu_val.setFoto(foto);
                    ibu_val.setHp(hp);
                    ibu_val.setKtp(ktp);
                    ibu_val.setNama(nama);
                    ibu_val.setPrivilege(privilege);
                    ibu_val.setTtl(ttl);

                    // Here the List ibu_ibu is not NULL
                    ibu_ibu.add(ibu_val);
                }
            }

            @Override
            public void onCancelled(DatabaseError error) {
                // Failed to read value
                Log.w("Hello", "Failed to read value.", error.toException());
            }
        });
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
       Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_dashboard_list, container, false);

        RecyclerView myrv = (RecyclerView) view.findViewById(R.id.dashboard_recycler_view);

        //Here the List ibu_ibu is null
        adapter_list_ibu myAdapter = new adapter_list_ibu(ibu_ibu);
        LinearLayoutManager LinearLayoutManager = new LinearLayoutManager(getContext());
        myrv.setLayoutManager(LinearLayoutManager);
        myrv.setAdapter(myAdapter);
        return view;
    }
}

I expected the List to be not NULL inside OnCreateView so the Fragment wont Blank

LeoColman
  • 6,950
  • 7
  • 34
  • 63
dpustakan
  • 33
  • 3
  • 2
    Welcome to Stack Overflow. Please don't tag questions with IDE tags (android-studio) just because you use that IDE: these tags should only be used when you have questions about the IDE itself, and not any code you write in it. See [when is it appropriate to remove an IDE tag](https://meta.stackoverflow.com/a/315196/6296561) – MD Naseem Ashraf Apr 10 '19 at 11:41

1 Answers1

2

Firebase APIs are asynchronous, which means that onDataChange() method returns immediately after it's invoked, and the callback will be called some time later. There are no guarantees about how long it will take. So it may take from a few hundred milliseconds to a few seconds before that data is available.

Because that method returns immediately, your ibu_val list that you're trying to use it outside the onDataChange() method, will not have been populated from the callback yet and that's why is always empty.

Basically, you're trying to use a value of variable synchronously from an API that's asynchronous. That's not a good idea, you should handle the APIs asynchronously as intended.

A quick solve for this problem would be to notify the adapter once you got all elements from the database using:

myrv.notifyDatasetChanged();

So add this line of code right after where the for loop ends.

If you intent to use that list outside the callback, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193