【问题标题】:Retrieve child from firebase database in android从android中的firebase数据库中检索孩子
【发布时间】:2019-09-13 14:26:16
【问题描述】:

我试图从我的 firebase 中检索 2 个数据分支,但是我得到了一个 nullpointException,我不知道为什么

这是数据库

获取烹饪时间和类别的代码

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

食谱类

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




    }

还有例外

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'

我为数据库创建了一个有效的配方类,因为我之前尝试过,当时数据库中只有一个配方

感谢您的帮助

【问题讨论】:

  • 您的 recipe_test 对象是 null。向我们展示您的Recipe 课程的内容。
  • Doesnt getValue() 需要类字段的公共设置器吗?似乎 SDK 找不到该字段的设置器,这就是为什么总是有空值的原因。您在控制台中是否有任何来自 Firebase SDK 的日志?

标签: android firebase firebase-realtime-database


【解决方案1】:

使用.getValue()时,注意:

此方法用于编组此快照中包含的数据 进入您选择的类别。该类必须适合2个简单的 约束:

  1. 该类必须有一个不带参数的默认构造函数
  2. 该类必须为要分配的属性定义公共 getter。没有公共 getter 的属性将被设置为 实例反序列化时的默认值

我建议在定义类变量后,在 Android Studio 中执行 Alt+Insert 以生成公共 getters-setters。

此外,正如弗兰克在他的回答中指出的那样,您将通过执行以下操作收到“食谱”下的所有食谱:

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

现在在 for-each 循环中,您需要使用这些值。例如,当您想要具有 key = "recipe_2" 的快照时,您需要这样做:

if( snapshot.getKey().equals("recipe_2")) {
    //do your stuff
}

完整代码:

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

【讨论】:

  • 酷,乐于助人!
【解决方案2】:

您正在收听recipes,然后循环播放它下面的孩子。这意味着在第一次迭代中,snapshot 将指向 recipe_1,并且您不再需要为该孩子指定子地址:

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

如果您想明确获取某些食谱,请摆脱循环并使用直接child("...") 访问:

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

【讨论】:

  • 但如果我想从 recipe_2 获取信息,则此代码无法使用 Recipe recipe_test = snapshot.child("recipe_2").getValue(Recipe.class);
  • @TimonDoo 您需要检查该快照的密钥是否等于“recipe_2”,检查我的答案
  • 我添加了一个示例,说明如何在我的答案中明确获取特定食谱。
猜你喜欢
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
  • 1970-01-01
  • 1970-01-01
  • 2017-01-28
相关资源
最近更新 更多