-1

I try to get single record from my Firebase database and convert it as an object from Kategori class, determined by its id_kategor' attributes.

public class Kategori {

  private String nama_id;
  private String nama_en;
  private String id_kategori;
  private Integer jml_item = 0;
  private Integer jml_brand = 0;

  public Kategori(){}

  public Kategori(String id_kategori) {
    this.id_kategori = id_kategori;
    this.fetchData();
  }

  private void fetchData(){
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference myRef = database.getReference("kategori");

    myRef.child( this.id_kategori ).addListenerForSingleValueEvent(new ValueEventListener (){

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if( dataSnapshot.exists() ){
                String nama_en = dataSnapshot.child("nama_en").getValue(String.class);
                String nama_id = dataSnapshot.child("nama_id").getValue(String.class);

                Kategori.this.nama_en = nama_en;
                Kategori.this.nama_id = nama_id;

                Log.d(">>>>>> CHECK 1 >>>>>",Kategori.this.nama_en);
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

    //Log.d(">>>>>> CHECK 2 >>>>>",this.nama_en);
  }
}

I expect all attributes can get its correct value from Firebase.

Logs with tag CHECK 1 shows the correct result that means successfully get its values from Firebase. But logs with tag CHECK 2 gives me run-time error *"java.lang.NullPointerException: println needs a message"*, that means **'nama_en'** attribute has *null* value, and also means the attribut failed to get it's value from Firebase ValueEventListener

What is exactly the problem?

Here is my data samples

enter image description here

KENdi
  • 7,576
  • 2
  • 16
  • 31
Sofyan Thayf
  • 1,322
  • 2
  • 14
  • 26
  • Could you check your firebase data again, I see it's an en field that's returning null, so in the case that the en is a number or another data type, add the " " quotes to it, to make firebase recognize it as a string – Mofe Ejegi Dec 03 '17 at 14:49
  • Thank you for your response, but I think my Firebase data have no problem because `CHECK 1` Logs give me the correct result from database. Also my data id using alphanumeric and start with an alphabet. For make sure, I just added screenshoot of my data samples on Firebase in my question – Sofyan Thayf Dec 03 '17 at 15:07
  • 1
    As Izruo explains this is the expected behavior. Data is loaded from Firebase (and most of the modern web) asynchronously and your `onDataChange` method is only invoked long after the `check 2` is logged and the function has `fetchData` returned. The solution is to move any code that needs the data from Firebase *into* `onDataChange` (or invoke it from there). For a longer explanation see https://stackoverflow.com/q/33203379, https://stackoverflow.com/q/42596777, and https://stackoverflow.com/q/31700830. – Frank van Puffelen Dec 03 '17 at 16:17

1 Answers1

1

Check 2 might run before Check 1 and especially before nama_en is initialized.

The point here is that addListenerForSingleValueEvent adds the inner class as listener, but it does not immediately execute the code in it. Instead it directly continues with the Check 2 debug statement.
In particular name_en is initialized onDataChange, hence when the method is called, which should happen when whatever data is changed (I'm not familiar with Firebase API).

You can check this behavior by activating both debug statements at once and maybe use String.valueOf(Object o), so you don't run into NPEs, but still see the null value.

Izruo
  • 2,246
  • 1
  • 11
  • 23
  • Thank you. Yes, I think so, ** `CHECK 2`** might be run before ** `CHECK 1`**. also when I use the attributes value, maybe they still have no data, because the method not executed yet. It's a synchronous :( Where should I put the code to capture and use the result data – Sofyan Thayf Dec 03 '17 at 15:19