Reputation: 153
Im trying to retrieve 2 databranches from my firebase but um getting a nullpointException and i dont know why
Here is the Database
The code for retrieving the cookingTime and the category
FirebaseDatabase.getInstance().getReference().child( "recipes" )
.addListenerForSingleValueEvent( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
/*Recipe recipe = snapshot.getValue( Recipe.class );*/
DatabaseReference recipes = FirebaseDatabase.getInstance().getReference("recipes");
Recipe recipe_test = snapshot.child( "recipe_1" ).getValue(Recipe.class);
category.setText( recipe_test.getCategory() );
cookinTime.setText( recipe_test.getCookingtime() );
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
} );
}
the recipe class
package com.example.myapplicationdatatest;
import java.lang.reflect.Array;
import java.util.List;
import java.util.Map;
public class Recipe {
private String category;
private long cookingtime;
private String description;
private Map<String, Object> amountOfIngredients;
private String nameOfRecipe;
private Map<String, Object> Ingredients;
public Recipe() {};
public Recipe(String category, long cookingtime, String description,Map<String, Object> amountOfIngredients, String nameOfRecipe, Map<String, Object> Ingridients) {
this.category=category;
this.cookingtime=cookingtime;
this.description=description;
this.amountOfIngredients=amountOfIngredients;
this.nameOfRecipe=nameOfRecipe;
this.Ingredients=Ingridients;
}
public String getCategory() {
return category;
}
public String getCookingtime() {
long ct = cookingtime;
String result = String.valueOf( ct );
return result;
}
public String getDescription() {
return description;
}
public Map<String, Object> getAmountOfIngredients() {
return amountOfIngredients;
}
public String getNameOfRecipe() {
return nameOfRecipe;
}
public Map<String, Object> getIngredients() {
return Ingredients;
}
}
and the exception
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplicationdatatest, PID: 20846
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.myapplicationdatatest.Recipe.getCategory()' on a null object reference
at com.example.myapplicationdatatest.MainActivity$1.onDataChange(MainActivity.java:73)
at com.google.firebase.database.Query$1.onDataChange(com.google.firebase:firebase-database@@19.1.0:179)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.1.0:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.1.0:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.1.0:55)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
I/Process: Sending signal. PID: 20846 SIG: 9
Disconnected from the target VM, address: 'localhost:8611', transport: 'socket'
I createdd a recipe class for the database which works, because i tried it before when there was only one recipe in the database
thx for your help
Upvotes: 1
Views: 601
Reputation: 598668
You're listening to recipes
and then looping over the children under it. That means in the first iteration snapshot
will point to recipe_1
already, and you don't need to subaddress for that child anymore:
FirebaseDatabase.getInstance().getReference().child( "recipes" )
.addListenerForSingleValueEvent( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Recipe recipe_test = snapshot.getValue( Recipe.class );
If you want to explicitly get certain recipes, get rid of the loop and use direct child("...")
access:
FirebaseDatabase.getInstance().getReference().child( "recipes" )
.addListenerForSingleValueEvent( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Recipe recipe1 = dataSnapshot.child("recipe_1").getValue( Recipe.class );
Recipe recipe2 = dataSnapshot.child("recipe_2").getValue( Recipe.class );
Upvotes: 2
Reputation: 3576
When using .getValue()
, note that:
This method is used to marshall the data contained in this snapshot into a class of your choosing. The class must fit 2 simple constraints:
- The class must have a default constructor that takes no arguments
- The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized
I suggest that after defining the class variable just do Alt+Insert
in Android Studio to generate the public getters-setters.
Moreover, as pointed by Frank in his answer, you will receive all the recipes under "recipes" by doing this:
FirebaseDatabase.getInstance().getReference().child( "recipes" )
.addListenerForSingleValueEvent( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Recipe recipe_test = snapshot.getValue( Recipe.class );
}
});
Now inside the for-each loop you need to use the values. For example when you want snapshot having key = "recipe_2" you need to do this:
if( snapshot.getKey().equals("recipe_2")) {
//do your stuff
}
Full code:
FirebaseDatabase.getInstance().getReference().child( "recipes" )
.addListenerForSingleValueEvent( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
if( snapshot.getKey().equals("recipe_2")) {
//do your stuff
Recipe recipe_2 = snapshot.getValue( Recipe.class );
}
}
});
Upvotes: 2