Reputation: 352
I come to solicit your help on a problem that I have with my application.
The problem is this: there are posts on the newsfeed that are in the database under this Posts -> [postid] location as on this capture
, and when a user save a post, in the database it is stored like this: Users -> [userid] -> saves -> [postid], as you can see in this screenshot
.
And I want that based on the id of the post that will be in save of the user, that he can retrieve the information details (like post description) on these posts and displayed them in my fragment "Saves" of my application.
Here is what I tried to do
THE SAVE FRAGMENT ADAPTER
package com.ackerman.ubi.Adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.ackerman.ubi.Model.PostModel;
import com.ackerman.ubi.R;
import com.bumptech.glide.Glide;
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.HashMap;
import java.util.List;
import java.util.Map;
public class SaveAdapter extends RecyclerView.Adapter<SaveAdapter.ViewHolder> {
private Context mContext;
private List<PostModel> mPostModel;
public SaveAdapter(Context mContext, List<PostModel> mPostModel) {
this.mContext = mContext;
this.mPostModel = mPostModel;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_save, parent, false);
return new SaveAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
PostModel post = mPostModel.get(position);
adaptSave(post, holder.post_image, holder.description, holder.price, holder.location, holder.product_state, holder.title);
}
@Override
public int getItemCount() {
return mPostModel.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView post_image;
TextView description, price, location, product_state, title;
ViewHolder(@NonNull View itemView) {
super(itemView);
post_image = itemView.findViewById(R.id.post_image);
description = itemView.findViewById(R.id.description);
price = itemView.findViewById(R.id.price);
location = itemView.findViewById(R.id.location);
product_state = itemView.findViewById(R.id.product_state);
title = itemView.findViewById(R.id.title);
}
}
//END OF ADAPTER SECTION
//METHOD SECTION
/**
* Methode permettat d'adapter les sauvegarde
*
* @param post
* @param postImage
* @param description
* @param price
* @param location
* @param productState
* @param title
*/
private void adaptSave(final PostModel post, final ImageView postImage, final TextView description, final TextView price, final TextView location, final TextView productState, final TextView title) {
Glide.with(mContext).load(post.getPostimage()).into(postImage);
//description.setText(post.get("description").toString());
// price.setText(post.get("price").toString());
// location.setText(post.get("location").toString());
// productState.setText(post.get("product_state").toString());
// title.setText(post.get("title").toString());
// description.setText(post.getDescription());
// title.setText(post.getTitle());
//
// price.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_price_tag_post, 0, 0);
// price.setText(post.getPrice());
//
// location.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_placeholder_post, 0, 0);
// location.setText(post.getLocation());
//
// getProductState(post, productState);
}
/**
* Methode permettant de verifier l'etat du produit
*
* @param post
* @param productState
*/
private void getProductState(PostModel post, TextView productState) {
String product_state = post.getProduct_state();
if (product_state.equals("Neuf")) {
productState.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_box_new_post, 0, 0);
} else {
productState.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_box_used_post, 0, 0);
}
}
}
THE SAVE FRAGMENT
package com.ackerman.ubi.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.ackerman.ubi.Adapter.SaveAdapter;
import com.ackerman.ubi.Model.PostModel;
import com.ackerman.ubi.R;
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;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import es.dmoral.toasty.Toasty;
public class SaveFragment extends Fragment {
private List<PostModel> saveList;
private SaveAdapter saveAdapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_save, container, false);
RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
saveList = new ArrayList<>();
saveAdapter = new SaveAdapter(getContext(), saveList);
recyclerView.setAdapter(saveAdapter);
getSaves();
return view;
}
/**
* Methode permettant de recuperer toute les sauvegardes de l'utilisateur
*/
private void getSaves() {
String userid = FirebaseAuth.getInstance().getCurrentUser().getUid(); //Recuperation de l'ID de l'utilisateur
//Reference de l'emplacement des posts, Users -> ID de l'utilisateur -> saves
DatabaseReference saveReference = FirebaseDatabase.getInstance().getReference("Users").child(userid).child("saves");
saveReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
saveList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
PostModel save = snapshot.getValue(PostModel.class);
saveList.add(save);
saveAdapter.notifyDataSetChanged();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
THE POST MODEL
package com.ackerman.ubi.Model;
public class PostModel {
//Ensemble des attribus que peut avoir un post
private String postid, postimage, description, publisher, location, price, product_state, title;
//Constructeur vide (Obligatoire(pour une initialisation))
public PostModel() {
}
/**
* Constructeur contenant les attributs de nos post
*
* @param postid
* @param postimage
* @param description
* @param publisher
* @param location
* @param price
* @param product_state
* @param title
*/
public PostModel(String postid, String postimage, String description, String publisher, String location, String price, String product_state, String title) {
this.postid = postid;
this.postimage = postimage;
this.description = description;
this.publisher = publisher;
this.location = location;
this.price = price;
this.product_state = product_state;
this.title = title;
}
//Les getters et les setters
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getProduct_state() {
return product_state;
}
public void setProduct_state(String product_state) {
this.product_state = product_state;
}
public String getPostid() {
return postid;
}
public void setPostid(String postid) {
this.postid = postid;
}
public String getPostimage() {
return postimage;
}
public void setPostimage(String postimage) {
this.postimage = postimage;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
}
but I get this error. THE ERROR WHAT I GET
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ackerman.ubi, PID: 6313
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.ackerman.ubi.Model.PostModel
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database@@19.1.0:418)
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.ackerman.ubi.Fragment.SaveFragment$1.onDataChange(SaveFragment.java:73)
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:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6688)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
the error occurs at this line "Postmodel save = snapshot.getValue (PostModel.class);" in the SaveFragment
I hope I was quite understandable if not hesitate to ask me questions. Thank you
Upvotes: 0
Views: 219
Reputation: 600091
It looks like the error comes from this line:
PostModel save = snapshot.getValue(PostModel.class);
This line loads data from FirebaseDatabase.getInstance().getReference("Users").child(userid).child("saves")
, which is the path /Users/$uid/saves
. Under that path in your screenshots, I see a structure like this:
So by the time you loop over dataSnapshot.getChildren()
, each individual value is just a string. Your PostModel
class has way more properties than exist in this location, which is why Firebase tells you that it Can't convert object of type java.lang.String to type com.ackerman.ubi.Model.PostModel
.
If you want to load the post that is referenced by this ID, you need to do an extra call to the database:
String modelKey = snapshot.getValue(String.class);
DatabaseReference postRef = FirebaseDatabase.getInstance().getReference("Posts").child(modelKey);
postRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot postSnapshot) {
PostModel save = postSnapshot.getValue(PostModel.class);
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
Upvotes: 3