0

See, I am trying to get these data from firebase using a model class. And also to display these data in real time even if the data changes. However, I am currently stuck with this error.

com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.codeworm.barkapp.m_Model.LocationModel
                                                                      at com.google.android.gms.internal.zzelw.zzb(Unknown Source)
                                                                      at com.google.android.gms.internal.zzelw.zza(Unknown Source)
                                                                      at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
                                                                      at com.codeworm.barkapp.m_FireBase.FirebaseHelper.fetchData(FirebaseHelper.java:64)
                                                                      at com.codeworm.barkapp.m_FireBase.FirebaseHelper.access$000(FirebaseHelper.java:20)
                                                                      at com.codeworm.barkapp.m_FireBase.FirebaseHelper$1.onChildAdded(FirebaseHelper.java:77)
                                                                      at com.google.android.gms.internal.zzecw.zza(Unknown Source)
                                                                      at com.google.android.gms.internal.zzeia.zzbyc(Unknown Source)
                                                                      at com.google.android.gms.internal.zzeig.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:135)
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5930)
                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                      at java.lang.reflect.Method.invoke(Method.java:372)
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)

image attached below is my database structure My firebase structure (UPDATED)

Here is my Model class

public class LocationModel {
Long lat,lng,ratio,total_slot;
String name;

public LocationModel(){

}
public Long getLat(){return lat;}
public void setLat(){this.lat=lat;}

public Long getLng(){return lng;}
public void setLng(){this.lng=lng;}


public Long getRatio(){ return ratio;}
public void setRatio(Long ratio){this.ratio = ratio;}

public Long getTotalSlot(){ return total_slot;}
public void setTotalSlot(Long total_slot){this.total_slot = total_slot;}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}

My helper class

   public FirebaseHelper(DatabaseReference db) {
    this.db = db;
}

//IMPLEMENT FETCH DATA AND FILL ARRAYLIST
private void fetchData(DataSnapshot dataSnapshot)
{
    locationModels.clear();

    for (DataSnapshot ds : dataSnapshot.getChildren())
    {

        LocationModel locationModel=ds.getValue(LocationModel.class);
        locationModels.add(locationModel);


    }
}

//RETRIEVE
public ArrayList<LocationModel> retrieve()
{
    db.child("locs").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 locationModels;
}

My adapter

public class ParkingListAdapter extends BaseAdapter {
Context c;
ArrayList<LocationModel> locationModels;

public ParkingListAdapter(Context c, ArrayList<LocationModel> locationModels) {
    this.c = c;
    this.locationModels = locationModels;
}

@Override
public int getCount() {
    return locationModels.size();
}

@Override
public Object getItem(int position) {
    return locationModels.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView==null)
    {

        convertView= LayoutInflater.from(c).inflate(R.layout.model,parent,false);
    }

    TextView nameTxt= (TextView) convertView.findViewById(R.id.nameTxt);
    TextView ratioTxt= (TextView) convertView.findViewById(R.id.ratioTxt);
    TextView totalTxt= (TextView) convertView.findViewById(R.id.totalTxt);



    final LocationModel s= (LocationModel) this.getItem(position);

    nameTxt.setText(s.getName());
    ratioTxt.setText(String.valueOf(s.getRatio()));
    totalTxt.setText(String.valueOf(s.getTotalSlot()));

    //ONITECLICK
    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(c,s.getName(),Toast.LENGTH_SHORT).show();
        }
    });
    return convertView;
}

}

and finally my activity

        //INITIALIZE FIREBASE DB
    db = FirebaseDatabase.getInstance().getReference();
    helper = new FirebaseHelper(db);

    //ADAPTER
    adapter = new ParkingListAdapter(this, helper.retrieve());
    lv.setAdapter(adapter);
    adapter.notifyDataSetChanged();

    db.child("locs").addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            adapter.notifyDataSetChanged();

        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            adapter.notifyDataSetChanged();


        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

I really don't get why this error keeps on showing. If anyone can help me with this error it would mean so much please.

mppaler
  • 1
  • 1
  • You can use `return locationModels;` because that list is not loaded yet. – Alex Mamo Mar 12 '18 at 15:35
  • Your getter/setters for latitude/longitude need to match db - code has 'getLat' and db has latitude. It uses reflection to find them. –  Mar 12 '18 at 15:42
  • Also latitude and longitude should not be treated as Longs. –  Mar 12 '18 at 15:49
  • @Andy I have already updated my firebase data latitude, longitude to lat, lng. I still get the same error. Also, I have tried to put only String in my LocationModel class and all String in firebase and I still get the same error. – mppaler Mar 12 '18 at 16:55
  • Seems like a child of 'locs' is a Location so I don't see why you are then looping on its children (which would be the elements of Location1 in your example) so in fetchData just do dataSnapshot.getValue(Location.class). –  Mar 12 '18 at 17:10
  • @Andy The error was gone wow! However, it only displays data in Location1. And if I add Location2, only Location2 gets displayed. What if I want to add another Location like Location2, and display all of the children data? – mppaler Mar 12 '18 at 17:33
  • The child listener (on 'locs') will be called per child - so if 3 locations were added it would be invoked 3 times. So you should be ok - you just need to properly manage "locationModels" - don't clear it on each fetch - and you'll need to differentiate between and 'add' and 'update'. –  Mar 12 '18 at 17:38
  • @Andy Thank you I have removed the clear. The fetchdata is now only called for adding in the onChildAdded. It works! Thank you so much! Now my one problem left is, what if I want to change the data? in real time? I should get the key right? But how will I do that with my LocationModel.class in the onChildChanged? – mppaler Mar 12 '18 at 18:07
  • If you are using an ArrayList then implement 'equals' on the LocationModel class (to compare against the name field? if that is unique). Then on updates you can use the ArrayList.remove(Object) form (which will implicitly use your LocationModel.equals) and then re-add. Assuming a delete/add is OK for you change events. If you don't want to remove/re-add then you'll have to figure out which fields changed and update them but that should not be needed in the code you presented. –  Mar 12 '18 at 18:13
  • You are also correct that you could use the 'getKey' as well but you'll have to add that value to the LocationModels class and use that for the "equality" check. –  Mar 12 '18 at 18:20
  • @Andy Do you have any possible reference/links for it that might help? Thank you again in advance! – mppaler Mar 12 '18 at 18:53
  • @Andy If you're free to help. Here's my new link for my problem. [Firebase realtime updating onChildChanged](https://stackoverflow.com/questions/49250387/retrieve-data-from-firebase-in-real-time?noredirect=1#comment85507790_49250387) Badly needed help. – mppaler Mar 13 '18 at 14:11

0 Answers0