简体   繁体   中英

Retrieve child from firebase database in android

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

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 );

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:

  1. The class must have a default constructor that takes no arguments
  2. 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 );
                }
            }
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM