2

Hey im relatively new to firebase and programming as well so im sorry if its kind of a stupid question. im struggling with retrieving a recipe

Imgur

above is the datatree from firebase and below is the code from the MainActivity

       package com.example.myapplicationdatatest;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

public class MainActivity extends AppCompatActivity {

    private TextView category;
    private TextView cookinTime;
    private TextView description;
    private TextView ingridients;
    private TextView nameOfRecipe;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );
        category = findViewById( R.id.category );
        cookinTime = findViewById( R.id.cookingTime );
        description = findViewById( R.id.description );
        ingridients = findViewById( R.id.ingridients );
        nameOfRecipe = findViewById( R.id.nameOfRecipe );
        FirebaseApp.initializeApp( getApplicationContext() );






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

                            category.setText( recipe.getCategory() );
                            cookinTime.setText( recipe.getCookingtime() );
                            description.setText( recipe.getDescription() );
                            ingridients.setText( recipe.getIngredients() );
                            nameOfRecipe.setText( recipe.getIngredients() );
                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                    }
                } );
    }





}

The Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/category"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

      />

    <TextView
        android:id="@+id/cookingTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/description"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/ingridients"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/nameOfRecipe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>

the recipe class

    package com.example.myapplicationdatatest;

public class Recipe {

    private String category;
    private String cookingtime;
    private String description;
    private String ingredients;
    private String nameOfRecipe;

    public Recipe() {};

    public Recipe(String category, String cookingtime, String description,String ingredients, String nameOfRecipe) {
        this.category=category;
        this.cookingtime=cookingtime;
        this.description=description;
        this.ingredients=ingredients;
        this.nameOfRecipe=nameOfRecipe;
    }

    public String getCategory() {
        return category;
    }

    public String getCookingtime() {
        return cookingtime;
    }

    public String getDescription() {
        return description;
    }

    public String getIngredients() {
        return ingredients;
    }

    public String getNameOfRecipe() {
        return nameOfRecipe;
    }
}

and the Exception

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapplicationdatatest, PID: 6400
    com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertString(com.google.firebase:firebase-database@@19.1.0:408)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database@@19.1.0:199)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToType(com.google.firebase:firebase-database@@19.1.0:178)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.access$100(com.google.firebase:firebase-database@@19.1.0:47)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-database@@19.1.0:586)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-database@@19.1.0:545)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database@@19.1.0:415)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database@@19.1.0:214)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database@@19.1.0:79)
        at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database@@19.1.0:203)
        at com.example.myapplicationdatatest.MainActivity$1.onDataChange(MainActivity.java:53)
        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 really dont know how i can retrieve these multiple branches, especially since i want to add more than one recipe

thanks for your help

Timon Doo
  • 143
  • 12

2 Answers2

3

You are getting the following error:

com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String

Because the type of the fields in your Recipe class are different than the type of the properties in your database. You have in your Recipe class a field named ingredients which is of type String while in the database I see that is a Map<String, Object> and this is not correct, hence that error. The type of the fields must match. Beside that, you have a property in your database named amountOfIngredients which is actually missing from your Recipe class. To solve this, please model your Recipe class according to the type of your properties that exist in the database and your problem will be solved.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • ok, thats maybe a really stupid question but im trying to change the Map to an array with a code like this: public String[] getAmountOfIngredients(Map) { String[] result = new String[10]; Map.values().toArray(); return amountOfIngredients; } but i dont know the name of the Map, or am i missing something ? – Timon Doo Sep 12 '19 at 10:15
  • No, you cannot do that. You should simplu change the type of your variables in your class to match the one in the database. There are no arrays in database. Those objects are maps, as also your error says. Did you even try it? – Alex Mamo Sep 12 '19 at 10:19
  • Yes, it works, but the output looks something like this: {amount_ing_2=1,amount_ing_3=123} and i wanted to extract the numbers – Timon Doo Sep 12 '19 at 11:06
  • 1
    Good to hear that it worked :) In that case, [iterate through the map](https://stackoverflow.com/questions/46898/how-do-i-efficiently-iterate-over-each-entry-in-a-java-map) and get the desired data. Tell me if you solved it. – Alex Mamo Sep 12 '19 at 11:09
  • thank you so much for your help :) i will change my code when everything works – Timon Doo Sep 12 '19 at 11:11
  • oh yeah, wanted to check it after i finished the code, but was the answer to my problems, so thank you very much – Timon Doo Sep 12 '19 at 12:24
  • i found a solution which works for me, although it doesn´t seem right String[] result = new String[10]; result = Arrays.copyOf(recipe.getAmountOfIngredients().keySet().toArray(),recipe.getAmountOfIngredients().keySet().toArray().length,String[].class ); Collections.addAll( amountIngridients,result ); – Timon Doo Sep 12 '19 at 13:18
1

I think what you are trying to do is get all the recipes and go over them one by one. If this is the case try this:

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);//I'm assuming you have a Recipe class
               //Do something with the data
           }
     }
     @Override
     public void onCancelled(DatabaseError databaseError) {
     }
});

In your recipe class ingredients is not a String. It's a Hashmap. try:

public class Recipe {

    private String category;
    private String cookingtime;
    private String description;
    private HashMap<String, String> ingredients;
    private String nameOfRecipe;

    public Recipe() {};

    public Recipe(String category, String cookingtime, String description,HashMap<String, String>ingredients, String nameOfRecipe) {
        this.category=category;
        this.cookingtime=cookingtime;
        this.description=description;
        this.ingredients=ingredients;
        this.nameOfRecipe=nameOfRecipe;
    }

    public String getCategory() {
        return category;
    }

    public String getCookingtime() {
        return cookingtime;
    }

    public String getDescription() {
        return description;
    }

    public HashMap<String, String> getIngredients() {
        return ingredients;
    }

    public String getNameOfRecipe() {
        return nameOfRecipe;
    }
}
Itamar Kerbel
  • 2,508
  • 1
  • 22
  • 29