3

My Problem

      08-10 04:23:28.820 21501-21501/my.org.medicare.medicareapp E/AndroidRuntime: FATAL EXCEPTION: main                                              Process: my.org.medicare.medicareapp, PID: 21501                                             com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type my.org.medicare.medicareapp.protest
at com.google.android.gms.internal.zzaln.zzd(Unknown Source)
at com.google.android.gms.internal.zzaln.zzb(Unknown Source)
at com.google.android.gms.internal.zzaln.zza(Unknown Source)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
at my.org.medicare.medicareapp.FirebaseHelper.fetchData(FirebaseHelper.java:50)
at my.org.medicare.medicareapp.FirebaseHelper.access$000(FirebaseHelper.java:14)            atmy.org.medicare.medicareapp.FirebaseHelper$1.onChildAdded(FirebaseHelper.java60)at com.google.android.gms.internal.zzahe.zza(Unknown Source)                                      at com.google.android.gms.internal.zzaje.zzcta(Unknown Source)                          at com.google.android.gms.internal.zzajh$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

My Main Activity Code:

 rv = (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));
        //INITIALIZE FIREBASE DB
        db = FirebaseDatabase.getInstance().getReference().child("Pro");;

        helper = new FirebaseHelper(db);
        //ADAPTER
        adapter = new MyAdapter(this, helper.retrieve());
        rv.setAdapter(adapter);

And my FirebaseHelper:

public class FirebaseHelper {
    DatabaseReference db;
    Boolean saved=null;
    ArrayList<protest> spacecrafts=new ArrayList<>();

    public FirebaseHelper(DatabaseReference db) {
        this.db = db;
    }
    //WRITE IF NOT NULL
    public Boolean save(protest spacecraft)
    {
        if(spacecraft==null)
        {
            saved=false;
        }else
        {
            try
            {
                db.child("Pro").push().setValue(spacecraft);
                saved=true;
            }catch (DatabaseException e)
            {
                e.printStackTrace();
                saved=false;
            }
        }
        return saved;
    }

    //IMPLEMENT FETCH DATA AND FILL ARRAYLIST
    private void fetchData(DataSnapshot dataSnapshot)
    {
        spacecrafts.clear();
        //dataSnapshot.getChildren()
        for (DataSnapshot ds : dataSnapshot.getChildren())
        {
            protest spacecraft=ds.getValue(protest.class);
            spacecrafts.add(spacecraft);
        }
    }

    //READ THEN RETURN ARRAYLIST
    public ArrayList<protest> retrieve() {
        db.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                fetchData(dataSnapshot);
            }
            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                fetchData(dataSnapshot);
            }
            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
            }
            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
        return spacecrafts;
    }
}

My view Holder

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    TextView nameTxt,propTxt,descTxt;
    ItemClickListener itemClickListener;

    public MyViewHolder(View itemView) {
        super(itemView);
        nameTxt= (TextView) itemView.findViewById(R.id.nameTxt);
        propTxt= (TextView) itemView.findViewById(R.id.propellantTxt);
        descTxt= (TextView) itemView.findViewById(R.id.descTxt);
        itemView.setOnClickListener(this);
    }

    public void setItemClickListener(ItemClickListener itemClickListener)
    {
        this.itemClickListener=itemClickListener;
    }
    @Override
    public void onClick(View view) {
        this.itemClickListener.onItemClick(this.getLayoutPosition());
    }

Below is my data structure, I try to read "Pro"

Data Structure

My Protest structure:

public class protest {
    private String name;
    private String contact;
    private String centre;

    public protest(){};

    public String getName(){return name;}
    public String getContact(){return contact;}
    public String getCentre(){return centre;}
    public void setName(String name) {
        this.name = name;
    }
    public void setContact(String contact) {
        this.contact = contact;
    }
    public void setCentre(String centre) {
        this.centre = centre;
    }
}

May i know what is the problem? I am new to firebase and i need your help. I read some similar question here but i still can't solve my problem. Can any expert here help me?

Update: Tested again with print.. when Datasnapshot go to

  public ArrayList<protest> retrieve() {
        db.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                System.out.println(dataSnapshot.getValue());
                fetchData(dataSnapshot);
            }

08-10 06:26:47.548 26700-26700/my.org.medicare.medicareapp I/System.out: {name=lee, contact=123456, centre=jalan ipoh}

But when Datasnapshot go to

 private void fetchData(DataSnapshot dataSnapshot)
    {
        spacecrafts.clear();
        //dataSnapshot.getChildren()
        for (DataSnapshot ds : dataSnapshot.getChildren())
        {
            System.out.println(ds.getValue());
            protest spacecraft=ds.getValue(protest.class);
            spacecrafts.add(spacecraft);
        }
    }

08-10 06:26:47.548 26700-26700/my.org.medicare.medicareapp I/System.out: jalan ipoh

What is the problem?

5
  • print the dataSnapshot value and check it returns string or object Commented Aug 10, 2016 at 4:49
  • Hay this is Firebase com.google.firebase.database.DatabaseException Exception so try to tag Firebase Commented Aug 10, 2016 at 5:02
  • Dear USKMobility - 08-10 06:13:56.794 21719-21719/my.org.medicare.medicareapp I/System.out: {name=lee, contact=123456, centre=jalan ipoh} It return Object Commented Aug 10, 2016 at 6:16
  • in what line does the exception occur? Commented Aug 10, 2016 at 6:45
  • DataSnapshot value change from {name=lee, contact=123456, centre=jalan ipoh} to jalan ipoh. when i call fetchData function. I dont understand why data change Commented Aug 10, 2016 at 6:54

2 Answers 2

12

Your fetchData function already receives DataSnapshot as a child-node, but even here you still loop through the children which will effectively be looping through individual keys (name, contact, centre). You should simply call getValue on DataSnaphot without looping:

private void fetchData(DataSnapshot dataSnapshot)
    {
        spacecrafts.clear();        
        protest spacecraft=dataSnapshot.getValue(protest.class);
        spacecrafts.add(spacecraft);        
    }

I hope this helps.

Sign up to request clarification or add additional context in comments.

6 Comments

Great, I am glad I could help. Please vote the answer if you found it helpful.
I am glad you found it useful as well - it was indeed an interesting "problem" to troubleshoot.
@ishmaelMakitla this helped a lot. if i was querying for five items from my firebase database, will onChildAdded() be called once or five times?
As far as I understand - it should be called for each child you traverse. The "trouble" with addChildEventListener is that you have really no easy way of knowing when the query has ended (seen all children) - because it does not really end - in such cases you use value-event-listener instead.
@ishmaelMakitla I must be misunderstanding something. Doesn't calling '.clear()' remove every element from the list each time one is supposed to be added?
|
0

Most likely this is your problem, in your fetchData method:

private void fetchData(DataSnapshot dataSnapshot)
{
    spacecrafts.clear();
    //dataSnapshot.getChildren()
    for (DataSnapshot ds : dataSnapshot.getChildren()) //--> At this point, ds is an iterator of dataSnapshot; it will iterate the dataSnapshot's children. In this case, the first child's type is String, thus the first iteration of ds will have a type of String. 
    {
        System.out.println(ds.getValue());
        protest spacecraft=ds.getValue(protest.class); //--> at this point, you tried to assign a String to an Object with type "protest" by conversion. This is illegal, so it will throw an exception instead.
        spacecrafts.add(spacecraft);
    }
}

I hope this helps.

2 Comments

on a sidenote, I would suggest you to try to follow Java's naming convention on Class naming...I assume protest is a Class?
@cipley good answer. if i was querying for five items from my firebase database, will onChildAdded() be called once or five times?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.