Error while displaying data from Firebase Database to RecyclerView - java

We have been facing this error while our app tries to display data from our Firebase Database. Here is the error shown in logcat:
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.example.projectrefill.retailer_model_datewise_dispwhenpressed
Here is the screenshot of the database where we are trying to display data from
Retailer> Kamath Bakery> r_history > (date_with_time) > (number)> :
Java Class (retailerside_datewisetransaction_Fragment) :
FirebaseRecyclerOptions<retailer_model_datewise_dispwhenpressed> options =
new FirebaseRecyclerOptions.Builder<retailer_model_datewise_dispwhenpressed>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("Retailer").child(username).child("r_history").child(datenew),retailer_model_datewise_dispwhenpressed.class)
.build();
adapter=new adapter_retailerside_datewise_dispoforder(options);
adapter.startListening();
recyclerView.setAdapter(adapter);
Model Class (retailer_model_datewise_dispwhenpressed) :
public class retailer_model_datewise_dispwhenpressed {
String name,price,quan,totalamount,weight;
public retailer_model_datewise_dispwhenpressed() {
}
public retailer_model_datewise_dispwhenpressed(String name, String price, String quan, String totalamount, String weight) {
this.name = name;
this.price = price;
this.quan = quan;
this.totalamount = totalamount;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getQuan() {
return quan;
}
public void setQuan(String quan) {
this.quan = quan;
}
public String getTotalamount() {
return totalamount;
}
public void setTotalamount(String totalamount) {
this.totalamount = totalamount;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
}
Adapter Class (adapter_retailerside_datewise_dispoforder) :
public class adapter_retailerside_datewise_dispoforder extends FirebaseRecyclerAdapter<retailer_model_datewise_dispwhenpressed,adapter_retailerside_datewise_dispoforder.myviewholder> {
public adapter_retailerside_datewise_dispoforder(#NonNull FirebaseRecyclerOptions<retailer_model_datewise_dispwhenpressed> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull myviewholder holder, int position, #NonNull retailer_model_datewise_dispwhenpressed model) {
holder.name.setText("Name: "+model.getName());
holder.price.setText("Price: "+model.getPrice());
holder.quan.setText("Quan: "+model.getQuan());
holder.totprice.setText(model.getTotalamount());
holder.weight.setText("Weight: "+model.getWeight());
}
#NonNull
#Override
public myviewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row_retailer_datewise_whenpressed,parent,false);
return new myviewholder(view);
}
public class myviewholder extends RecyclerView.ViewHolder {
TextView name,price,quan,weight,totprice;
public myviewholder(#NonNull View itemView) {
super(itemView);
name=itemView.findViewById(R.id.datewisename);
price=itemView.findViewById(R.id.datewiseprice);
quan=itemView.findViewById(R.id.datewisequan);
weight=itemView.findViewById(R.id.datewiseweight);
totprice=itemView.findViewById(R.id.totalpricehere);
}
}
}

Since you pass this path to the FirebaseUI adapter:
FirebaseDatabase.getInstance().getReference().child("Retailer").child(username).child("r_history").child(datenew)
Firebase will read each child node under that path and try to create a retailer_model_datewise_dispwhenpressed object out of it.
This works fine for the child 1, as it has the properties that your class has. But then Firebase tries to do the same for Pmode, and that is just a string value, which is not a valid retailer_model_datewise_dispwhenpressed object.
You'll have to ensure that you only have child nodes that are valid retailer_model_datewise_dispwhenpressed objects under the path that you load.

Related

How to retrieve an object from firebase database?

I'm trying to retrieve an object from an ArrayList in the database but when I'm retrieving it one of the object attributes returns an empty string instead of the string saved in the database, however, the other attributes are returning their values.
The databse image:
getAmount returns the matching string from the database but getFoodName returns an empty string instead of "egg".
reference.child(userId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
User userProfile=snapshot.getValue(User.class);
if(userProfile!=null)
{
if(userProfile.morning_List!=null)
{
for(int i=0;i<userProfile.morning_List.size();i++)
{
FoodItem foodItem=new FoodItem(userProfile.morning_List.get(i));
mFoodList.add(new FoodItem(foodItem.getFoodName(),foodItem.getAmount()));
}
}
foodItem class
public class FoodItem {
private String fdName;
private String amount;
public FoodItem(String foodName, String foodAmount) {
this.fdName = foodName;
this.amount=foodAmount;
}
public String getFoodName() {
return this.fdName;
}
public String getAmount() {
return this.amount;
}
}
List adapter class:
public class FoodListAdapter extends RecyclerView.Adapter<FoodListAdapter.FoodViewHolder>{
private ArrayList<FoodItem> mFoodList;
public static class FoodViewHolder extends RecyclerView.ViewHolder{
public TextView mFoodName;
public TextView mAmount;
public FoodViewHolder(#NonNull View itemView,final OnItemClickListener listener) {
super(itemView);
mFoodName = itemView.findViewById(R.id.fdName);
mAmount = itemView.findViewById(R.id.amount);
}
}
public FoodListAdapter(ArrayList<FoodItem> foodList) {
mFoodList = foodList;
}
#NonNull
#Override
public FoodListAdapter.FoodViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_item, parent, false);
FoodViewHolder evh = new FoodViewHolder(v, mListener);
return evh;
}
#Override
public void onBindViewHolder(#NonNull FoodListAdapter.FoodViewHolder holder, int position) {
FoodItem currentItem = mFoodList.get(position);
holder.mFoodName.setText(currentItem.getFoodName());
holder.mAmount.setText(currentItem.getAmount());
}
#Override
public int getItemCount() {
return mFoodList.size();
}
}
I think this may come from the fact that your field is called fdName, while the property in the database is called foodName.
Firebase uses either the getter and setter to determine the name of the property, or if those are missing, the name of the field. So it's looking for a property called fdName in the database.
The solution is to rename your field to match the property name in the database:
public class FoodItem {
private String foodName; // πŸ‘ˆ
private String amount;
public FoodItem(String foodName, String foodAmount) {
this.foodName = foodName;
this.amount=foodAmount;
}
public String getFoodName() {
return this.foodName; // πŸ‘ˆ
}
public String getAmount() {
return this.amount;
}
}

Firestore using recyclerview I want to append a picture

I want to show people's information including a picture.
Here is User.class
public class User {
//νŒŒμ΄μ–΄ μŠ€ν† μ–΄ ν•„λ“œ λ³€μˆ˜λͺ…κ³Ό νƒ€μž…μ΄ κ°™μ•„μ•Ό ν•œλ‹€. ex) 프사 라즈 INTP ꡬ일 23
String name, mbti, region, age, profile_image;
public User(){
//must be empty
}
public User(String name, String mbti, String region, String age, String profile_image) {
this.name = name;
this.mbti = mbti;
this.region = region;
this.age = age;
this.profile_image = profile_image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMbti() { return mbti; }
public void setMbti(String mbti) {this.mbti = mbti; }
public String getRegion() { return region; }
public void setRegion(String region) { this.region = region; }
public String getAge() { return age; }
public void setAge(String age) { this.age = age; }
public String getProfile_image() { return profile_image; }
public void setProfile_image(String profile_image) { this.profile_image = profile_image; }}
And here is the MyAdapter class
Context context;
ArrayList<User> userArrayList;
public MyAdapter(Context context, ArrayList<User> userArrayList) {
this.context = context;
this.userArrayList = userArrayList;
}
#NonNull
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull MyAdapter.MyViewHolder holder, int position) {
User user = userArrayList.get(position);
holder.name.setText(user. name);
holder.mbti.setText(user.mbti);
holder.region.setText(user.region);
holder.age.setText(user.age);
Glide.with(context).load(user.getProfile_image()).into(holder.imgprofile);
}
#Override
public int getItemCount() {
return userArrayList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView name, mbti, region, age;
ImageView imgprofile;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.tvfirstName);
mbti = itemView.findViewById(R.id.item_mbti);
region = itemView.findViewById(R.id.item_region);
age = itemView.findViewById(R.id.item_age);
imgprofile = itemView.findViewById(R.id.main_profileimg);
}
}
In my MainActivity I use firestore.collection() and userArrayList.add(dc.getDocument().toObject(User.class)) So recyclerview can have people's information.
But Pictures are stored in Firebase storage -> profile/pics -> uid.jpg..
I'm beginner so I can't transform code userArrayList.add(dc.getDocument().toObject(User.class))
firestore.collection("Users")
.whereEqualTo("mbti",mainsearch_mbti)
.orderBy("time",Query.Direction.DESCENDING).limit(50)
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException error) {
if(error != null){
if(progressDialog.isShowing()){
progressDialog.dismiss();
}
Log.e("Firestore error",error.getMessage());
return;
}
for (DocumentChange dc : value.getDocumentChanges()){
if (dc.getType() == DocumentChange.Type.ADDED){
userArrayList.add(dc.getDocument().toObject(User.class));
}
myAdapter.notifyDataSetChanged();
if(progressDialog.isShowing()){
progressDialog.dismiss();
}
}
}
});
You can take data with value.getDocuments() function.
for (DocumentSnapshot snapshot : value.getDocuments()) {
Map<String,Object> dataMap = snapshot.getData();
String abc = (String) dataMap.get("abc");
}

Receiving null Parcelable object Android

I'm trying to pass an object from my RecyclerView adapter to a fragment using parcelable. However when I try to receive the data, the bundle is null. I've looked at other examples, but I can't see where I'm going wrong.
Parcelable class
public class Country extends BaseObservable implements Parcelable {
#SerializedName("name")
#Expose
private String name;
#SerializedName("snippet")
#Expose
private String snippet;
#SerializedName("country_id")
#Expose
private String countryId;
#SerializedName("id")
#Expose
private String id;
#SerializedName("coordinates")
#Expose
private Coordinates coordinates;
#SerializedName("images")
#Expose
private List<CountryImage> images;
protected Country(Parcel in) {
name = in.readString();
snippet = in.readString();
}
public static final Creator<Country> CREATOR = new Creator<Country>() {
#Override
public Country createFromParcel(Parcel in) {
return new Country(in);
}
#Override
public Country[] newArray(int size) {
return new Country[size];
}
};
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(snippet);
}
#Override
public int describeContents() {
return 0;
}
#Bindable
public String getCountryId() {
return countryId;
}
public void setCountryId(String countryId) {
this.countryId = countryId;
notifyPropertyChanged(BR.countryId);
}
#Bindable
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
notifyPropertyChanged(BR.id);
}
#Bindable
public Coordinates getCoordinates() {
return coordinates;
}
public void setCoordinates(Coordinates coordinates) {
this.coordinates = coordinates;
notifyPropertyChanged(BR.coordinates);
}
#Bindable
public List<CountryImage> getImages() {
return images;
}
public void setImages(List<CountryImage> images) {
this.images = images;
notifyPropertyChanged(BR.images);
}
#Bindable
public String getSnippet() {
return snippet;
}
public void setSnippet(String snippet) {
this.snippet = snippet;
notifyPropertyChanged(BR.snippet);
}
#Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
}
RetrofitAdapter.java
public class RetrofitAdapter extends RecyclerView.Adapter<RetrofitAdapter.MyViewHolder> implements CustomClickListener {
private List<Country> cities;
private CustomClickListener customClickListener;
private View view;
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
RetroItemBinding retroItemBinding =
DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()),
R.layout.retro_item, viewGroup, false);
view = viewGroup;
return new MyViewHolder(retroItemBinding);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.bindTo(cities.get(i));
myViewHolder.retroItemBinding.setItemClickListener(this);
}
#Override
public int getItemCount() {
if (cities != null) {
return cities.size();
} else {
return 0;
}
}
public void setCityList(ArrayList<Country> cities) {
this.cities = cities;
notifyDataSetChanged();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private RetroItemBinding retroItemBinding;
public MyViewHolder(#NonNull RetroItemBinding retroItemBinding) {
super(retroItemBinding.getRoot());
this.retroItemBinding = retroItemBinding;
}
void bindTo(Country country) {
retroItemBinding.setVariable(BR.city, country);
retroItemBinding.setVariable(BR.itemClickListener, customClickListener);
retroItemBinding.executePendingBindings();
}
}
public void cardClicked(Country country) {
CountryFragment countryFragment = new CountryFragment();
Bundle bundle = new Bundle();
bundle.putParcelable("Country", country);
countryFragment.setArguments(bundle);
((FragmentActivity) view.getContext()).getSupportFragmentManager().beginTransaction()
.replace(R.id.frag_container, new CountryFragment())
.commit();
}
}
Where I receive attempt to receive the data in CountryFragment.java
Country country;
Bundle bundle = this.getArguments();
if (bundle != null) {
country = bundle.getParcelable("Country");
}
.replace(R.id.frag_container, new CountryFragment())
should be
.replace(R.id.frag_container, countryFragment)
You are creating a second instance instead of passing the one you set the arguments on.

How do I store some background information associated with each item in a reyclerview in Android using Java?

I am building a social networking app using Cloud Firestore. My Firestore collection posts contains the following fields: title, text, uid, timestamp, latitude, longitude, photo url.
Now when I fetch these posts and display them on a RecyclerView. I do not want the uid, latitude, longitude to be visible on the UI but they should be associated with the item for further use when the item is clicked.
What is the proper way to make the given association?
This is my POJO class:
public class Post {
private String title;
private String dp;
private String description;
private double latitutude,longitude;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
private String uid;
public double getLatitutude() {
return latitutude;
}
public void setLatitutude(double latitutude) {
this.latitutude = latitutude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public String getDp() {
return dp;
}
public void setDp(String dp) {
this.dp = dp;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
This is the holder class:
public class PostHolder extends RecyclerView.ViewHolder {
ImageView dp;
TextView title,desc;
public PostHolder(#NonNull View itemView) {
super(itemView);
this.dp = itemView.findViewById(R.id.dpIV);
this.title = itemView.findViewById(R.id.titleTV);
this.desc = itemView.findViewById(R.id.descTV);
}
}
And this is the adapter:
public class PostAdapter extends RecyclerView.Adapter<PostHolder> {
Context c;
ArrayList<Post> posts;
public PostAdapter(Context c, ArrayList<Post> posts) {
this.c = c;
this.posts = posts;
}
#NonNull
#Override
public PostHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row,null);
return new PostHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PostHolder holder, int position) {
holder.title.setText(posts.get(position).getTitle());
holder.desc.setText(posts.get(position).getDescription());
//loadBitmap(position,holder.dp);
Glide.with(holder.dp.getContext())
.load(posts.get(position).getDp())
.diskCacheStrategy(DiskCacheStrategy.ALL)
.apply(RequestOptions.circleCropTransform())
.into(holder.dp);
}
#Override
public int getItemCount() {
Log.e("AdapterSIZE",posts.size()+"");
return posts.size();
}
}

I can not set Set Text in Card View name and surname

I have problem with set text in card view. I have 3 activist. First activity is list , second activity which show edit text which I complete data Person next acttivty 3 summary click buton go to MainActivty. When click to MainActitvty display error.
04-05 09:21:06.879 1035-1035/magdalena.pl.callmistake E/AndroidRuntime: FATAL EXCEPTION: main
Process: magdalena.pl.callmistake, PID: 1035
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String magdalena.pl.callmistake.Person.getName()' on a null object reference
at magdalena.pl.callmistake.PersonAdapter.onBindViewHolder(PersonAdapter.java:41)
at magdalena.pl.callmistake.PersonAdapter.onBindViewHolder(PersonAdapter.java:18)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6356)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6389)
at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5335)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5598)
my PersonAdapter
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.PersonViewHolder> {
public List<Person> personList = new ArrayList<>();
Person person;
private LayoutInflater layoutInflater;
public PersonAdapter(LayoutInflater layoutInflater) {
this.layoutInflater = layoutInflater;
}
#Override
public PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.
from(parent.getContext()).inflate(R.layout.item_card, parent, false);
return new PersonViewHolder(view);
}
#Override
public void onBindViewHolder(PersonViewHolder holder, int position) {
person = personList.get(position);
holder.name.setText(person.getName());
holder.surname.setText(person.getSurname());
}
#Override
public int getItemCount() {
return personList.size();
}
public void addPerson(Person person) {
int position = getItemCount();
personList.add(position, person);
notifyDataSetChanged();
}
public class PersonViewHolder extends RecyclerView.ViewHolder {
public TextView name, surname;
public PersonViewHolder(View itemView) {
super(itemView);
name = (TextView)itemView.findViewById(R.id.person_name);
surname = (TextView)itemView.findViewById(R.id.person_surname);
}
}
}
class Person
public class Person implements Parcelable
{
private String name;
private String surname;
private String email;
private String phone;
private String description;
protected Person(Parcel in) {
name = in.readString();
surname = in.readString();
email = in.readString();
phone = in.readString();
description = in.readString();
}
public Person(String name, String surname, String email, String phone, String description) {
this.name = name;
this.surname = surname;
this.email = email;
this.phone = phone;
this.description = description;
}
public String setName(String name) {
this.name = name;
return null;
}
public String getSurname() {
return surname;
}
public String setSurname(String surname) {
this.surname = surname;
return null;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public static Creator<Person> getCREATOR() {
return CREATOR;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
#Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
#Override
public Person[] newArray(int size) {
return new Person[size];
}
};
public String getName() {
return name;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeString(surname);
parcel.writeString(email);
parcel.writeString(phone);
parcel.writeString(description);
}
}
What is wrong ?
all code
https://github.com/Madzia123/CallInert
Apparently, In the onBindViewHolder method the person object is null. And you are trying to invoke getName() method on null reference. So it is causing the error. Make sure to have valid reference to Person object.
You are adding null person to personList at
public void addPerson(Person person) {
int position = getItemCount();
personList.add(position, person);
notifyDataSetChanged();
}
That's why when you call
person = personList.get(position);
it returns null
try this
public void addPerson(Person person) {
if(person==null){
Log.e("error","person is null");
return;
}
int position = getItemCount();
personList.add(position, person);
notifyDataSetChanged();
}
final Person person = personList.get(position);
holder.name.setText(person.getName());
From your attached logs, seems that you are getting NullPointerException when calling Person.getName() from your adapter's onBindViewHolder().
java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String magdalena.pl.callmistake.Person.getName()' on a null
object reference
Solution:
Update your PersonAdapter as below:
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.PersonViewHolder> {
Context context;
private LayoutInflater layoutInflater;
// Person List
public List<Person> personList;
public PersonAdapter(Context context, List<Person> persons) {
this.context = context;
this.personList = persons;
layoutInflater= LayoutInflater.from(context);
}
#Override
public PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.item_card, parent, false);
// View holder
PersonViewHolder holder = new PersonViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(PersonViewHolder holder, int position) {
// Person
Person person = personList.get(position);
holder.name.setText(person.getName());
holder.surname.setText(person.getSurname());
}
#Override
public int getItemCount() {
return personList.size();
}
public void addPerson(Person person) {
int position = getItemCount();
personList.add(position, person);
notifyDataSetChanged();
}
public class PersonViewHolder extends RecyclerView.ViewHolder {
public TextView name, surname;
public PersonViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.person_name);
surname = (TextView) itemView.findViewById(R.id.person_surname);
}
}
}
In your Activity do this:
..........
.................
Context mContext;
// RecyclerView
RecyclerView recyclerView;
PersonAdapter personAdapter;
RecyclerView.LayoutManager layoutManager;
// Values
List<Person> listPerson;
#Override
protected void onCreate(Bundle savedInstanceState) {
.......
............
// Context
mContext = this;
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// Set your recyclerView layout manager
// Person List
listPerson = new ArrayList<Person>();
// Add some person data to list from API call or from Database
// Here I added some for test purpose
listPerson.add(new Person("Hello Android", "Android", "google#gmail.com", "21132342423", "Lorem ipsum"));
listPerson.add(new Person("Hello Android", "Android", "google#gmail.com", "21132342423", "Lorem ipsum"));
// specify an adapter
personAdapter = new PersonAdapter(mContext, listPerson);
recyclerView.setAdapter(personAdapter);
}
...............
...........................
Hope this will help you~
first pass the data from where you call this adapter.
adapter = new PersonAdapter(getContext(),(ArrayList<Person>) list);
use arraylist.method to access class method.
holder.name.setText(person.personList(position).getName());

Categories