Issue
I am facing error While retrieving data from firebase Here is the error that i am receiving while getting data from firebase..
com.google.firebase.database.DatabaseException: Can't convert object of type java.util.ArrayList to type com.example.soas.POJO.Service at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database@@19.3.0:435) at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database@@19.3.0:231) at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database@@19.3.0:79) at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database@@19.3.0:203) at com.example.soas.Activities.Services$2.onDataChange(Services.java:80) at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.3.0:75) at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.3.0:63) at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.3.0:55) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 2020-11-03 14:53:29.178 9848-9848/com.example.soas I/Process: Sending signal. PID: 9848 SIG: 9
Firebase Database Structure:
Services.Java
package com.example.soas.Activities;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.soas.Adapters.ServiceAdapter;
import com.example.soas.POJO.Service;
import com.example.soas.R;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.auth.FirebaseAuth;
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;
import java.util.ArrayList;
public class Services extends AppCompatActivity {
RecyclerView recyclerView;
FloatingActionButton fab;
FirebaseDatabase database;
DatabaseReference reference;
ArrayList<Service> serviceList;
String user;
FirebaseAuth mAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_services);
database = FirebaseDatabase.getInstance();
recyclerView = findViewById(R.id.serviceRecycler);
fab = findViewById(R.id.fab);
mAuth = FirebaseAuth.getInstance();
user = mAuth.getCurrentUser().getUid();
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
database = FirebaseDatabase.getInstance();
reference = database.getReference("Services");
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Services.this, AddNewService.class);
startActivity(intent);
}
});
}
@Override
protected void onStart() {
super.onStart();
if (reference != null) {
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
serviceList = new ArrayList<>();
for (DataSnapshot ds: snapshot.getChildren()) {
if (ds.getKey().equals(user)) {
serviceList.add(ds.getValue(Service.class));
ServiceAdapter serviceAdapter = new ServiceAdapter(serviceList);
recyclerView = findViewById(R.id.serviceRecycler);
recyclerView.setAdapter(serviceAdapter);
}
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Services.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
}
Service.class(Object)
package com.example.soas.POJO;
public class Service {
public String name;
public Service() {
}
public Service(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ServiceAdapter.java
package com.example.soas.Adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.soas.POJO.Service;
import com.example.soas.R;
import java.util.ArrayList;
public class ServiceAdapter extends RecyclerView.Adapter<ServiceAdapter.MyViewHolder> {
ArrayList<Service> serviceList;
public ServiceAdapter(ArrayList<Service> serviceList) {
this.serviceList = serviceList;
}
@NonNull
@Override
public ServiceAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.service_item,viewGroup,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ServiceAdapter.MyViewHolder myViewHolder, int i) {
myViewHolder.name.setText(serviceList.get(i).getName());
// myViewHolder.price.setText(serviceList.get(i).getPrice());
}
@Override
public int getItemCount() {
return serviceList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView name, price;
public MyViewHolder(View view) {
super(view);
name = itemView.findViewById(R.id.vServiceName);
price = itemView.findViewById(R.id.servicePrice);
}
}
}
Solution
You're missing a for
loop over the 1
...4
children in your JSON. In addition: you're loading all Services
, while you only need the ones for the current user, so your code is wasting bandwidth and likely less secure.
To fix both problems, you can listen one level lower in the JSON tree, and update the code on onDataChange
to match:
reference.child(user).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
serviceList = new ArrayList<>();
for (DataSnapshot ds: snapshot.getChildren()) {
serviceList.add(ds.getValue(Service.class));
}
ServiceAdapter serviceAdapter = new ServiceAdapter(serviceList);
recyclerView = findViewById(R.id.serviceRecycler);
recyclerView.setAdapter(serviceAdapter);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Services.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Answered By - Frank van Puffelen
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.