I'm receiving these errors when I tried to populate a list view with firebase adapter using firebase UI
com.google.firebase.database.DatabaseException: Failed to convert
value of type java.util.HashMap to String
com.google.firebase.database.DatabaseException: Class
java.util.HashMap has generic type parameters, please use
GenericTypeIndicator instead
Here Is the code
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
DatabaseReference a = ref.child("info");
final FirebaseListAdapter<String> adapter =
new FirebaseListAdapter<String>(this,String.class,android.R.layout.simple_list_item_1,a) {
#Override
protected void populateView(View v, String model, int position) {
TextView text = (TextView) findViewById(android.R.id.text1);
text.setText(model);
}
here is an example of json data
"info" : {
"KSTUJILdwPN305Fs7ujhga4knlG3" : {
"File Info" : {
"-JFRkA855rfOU7GtcK4" : {
"Name" : "John",
"Adress" : "Test Adress",
"Favourite_food" : "Bread",
},
info node does not refer to your data model. It may contain children nodes. So to reach the model, you should use a reference like this.
DatabaseReference a = ref.child("info").child(info_id).child("File Info").child(file_id);
and you should have a FileInfo model instead of String model to use in
populateView(View v, FileInfo model, int position):
and model
public class FileInfo {
private String Name;
private String Adress;
private String Favourite_food;
public FileInfo() {
}
public FileInfo(String Name, String Adress, String Favourite_food) {
this.Name = Name;
this.Adress = Adress;
this.Favourite_food = Favourite_food;
}
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
public String getAdress() {
return Adress;
}
public void setAdress(String Adress) {
this.Adress = Adress;
}
public String getFavourite_food() {
return Favourite_food;
}
public void setFavourite_food(String Favourite_food) {
this.Favourite_food = Favourite_food;
}
}
final FirebaseListAdapter<String> adapter = new FirebaseListAdapter<String>(this,String.class,android.R.layout.simple_list_item_1,a)
public FirebaseListAdapter(Activity activity,
java.lang.Class<T> modelClass,
int modelLayout,
com.firebase.client.Firebase ref)
modelClass - Firebase will marshall the data at a location into an instance of a class that you provide
replace the constructor's 2nd parameter (String.class) with a POJO with the fields from info (name, address, favouriteFood)
FirebaseListAdapter
Edit:
You should also use getters in the populateView method
Related
I am trying to display an array that I stored in my Firestore to be displayed in a RecyclerView.
the error I'm receiving is this:
java.lang.RuntimeException: Could not deserialize object. Failed to convert value of type java.util.ArrayList to String
As for my codes, here it is:
model
public class ViewOrderModel implements Serializable {
String userName;
String phoneNumber;
String currentTime;
String address;
long totalPrice;
String itemList;
String documentID;
String productName;
int totalQuantity;
adapter
#Override
public void onBindViewHolder(#NonNull ViewOrderAdapter.ViewHolder holder, int position) {
holder.userName.setText(viewOrderModelList.get(position).getUserName());
holder.date.setText(viewOrderModelList.get(position).getCurrentTime());
holder.totalPrice.setText(String.valueOf(viewOrderModelList.get(position).getTotalPrice()));
holder.address.setText(viewOrderModelList.get(position).getAddress());
holder.phone.setText(viewOrderModelList.get(position).getPhoneNumber());
ViewOrderModel viewOrderModel = viewOrderModelList.get(position);
holder.productName.setText(viewOrderModel.getProductName());
holder.quantity.setText(viewOrderModel.getTotalQuantity());
}
activity
order_rec = findViewById(R.id.admin_view_order_rec);
order_rec.setLayoutManager(new LinearLayoutManager(this,RecyclerView.VERTICAL,false));
viewOrderModelList = new ArrayList<>();
viewOrderAdapter = new ViewOrderAdapter(this,viewOrderModelList);
order_rec.setAdapter(viewOrderAdapter);
firestore.collection("UserOrder")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (QueryDocumentSnapshot documentSnapshot : task.getResult()){
ViewOrderModel viewOrderModel = documentSnapshot.toObject(ViewOrderModel.class);
viewOrderModelList.add(viewOrderModel);
viewOrderAdapter.notifyDataSetChanged();
}
}
}
});
if it's needed this is my database
You are getting the following error:
java.lang.RuntimeException: Could not deserialize object. Failed to convert value of type java.util.ArrayList to String
Because you are trying to read a property of type array as a String, which is not possible in Java. To solve this, you have to change the type of your itemList filed in your ViewOrderModel class, to be a list. So please change:
String itemList;
Into:
List<Product> itemList;
This will work only as long as you have a class with a minimum declaration that looks like this:
class Product {
String documentID, productName;
int productPrice, totalPrice, totalQuantity;
}
I have list of object store in single document in Firestore. On my android side i am not able to fetch list of object and their inner data.
Here is code i am trying to fetch data
CollectionReference mCollectionReference = FirebaseFirestore.getInstance().collection("Categories");
mCollectionReference.document("Dinner Dishes").get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Collection<Object> objectMap = documentSnapshot.getData().values();
for(Object result:objectMap){
Sample obj = Sample.class.cast(result);
HashMap<String, String> pic = obj.getPic();
HashMap<String, String> name = obj.getName();
}
}
});
I need list of object i upload on Firestore in single document
My Model Class:
public class Sample {
private String name;
private String pic;
public Sample() {
}
public String getName() {
return name;
}
public String getPic() {
return pic;
}
}
You can convert it to a java object, if that is how you saved it?
ObjectType myObject = document.toObject(ObjectType.class);
I know there's a lot of similar questions like mine, but I've read and tried everything but still unable to solve this issue. What I am trying to achieve is to populate my listview with the data from the firebase. Im following a tutorial on youtube but Ive added some stuff, timestamp in particular. The error is in my for loop and says :
Class java.util.Map has generic type parameters, please use GenericTypeIndicator instead
This is my database looks like :
My Notes.java
public class Notes {
String noteId;
String noteCategory;
String note;
String rating;
public Map timeStamp;
public Notes(){
}
public Notes(String noteId, String noteCategory, String note, String rating, Map timeStamp) {
this.noteId = noteId;
this.noteCategory = noteCategory;
this.note = note;
this.rating = rating;
this.timeStamp = timeStamp;
}
public String getNoteId() {
return noteId;
}
public String getNoteCategory() {
return noteCategory;
}
public String getNote() {
return note;
}
public String getRating() {
return rating;
}
public Map<String,String> getTimeStamp() { return timeStamp;}
}
And below is my NoteList.java
#Override
protected void onStart() {
super.onStart();
databaseNotes.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
notesList.clear();
for(DataSnapshot noteSnapshot : dataSnapshot.getChildren()){
Notes notes = noteSnapshot.getValue(Notes.class);
notesList.add(notes);
}
NoteList adapter = new NoteList(MyNotes.this, notesList);
listViewNotes.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Any advice would be greatly appreciated! Thank you in advance.
EDIT : Okay, Ive tried the suggested answer, and after I logged the map it shows my data on the console. However, how do I iterate my map into the listview ?
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
From looking at your DB, it looks like you should use int or long type instead of the map type, since your timestamp has a number value
I have two activities, one to create an Assessment object, and another to list the Assessment objects in Firebase, however I've encountered an issue: the POJO is able to serialize to JSON just fine, however the FirebaseRecyclerAdapter doesn't seem to be able to return the JSON data to the object type.
Here is my object file:
#IgnoreExtraProperties
public class Assessment {
private String company;
private String industry;
private String location;
private String product;
private String ownerId;
private String ownerName;
private boolean isDraft;
private boolean isQuickWalk;
private Map<String, Category> categories;
public Assessment() {
// Default constructor required for calls to DataSnapshot.getValue()
}
public Assessment(String companyName, String industryName, String locationName,
String productName, String ownerId, String ownerName, boolean isDraft, boolean isQuickWalk, Map<String, Category> categories) {
this.company = companyName;
this.industry = industryName;
this.location = locationName;
this.product = productName;
this.ownerId = ownerId;
this.ownerName = ownerName;
this.isDraft = isDraft;
this.isQuickWalk = isQuickWalk;
this.categories = categories;
}
public String getCompanyName() {
return company;
}
public String getIndustryName() {
return industry;
}
public String getLocationName() {
return location;
}
public String getProductName() {
return product;
}
public String getOwnerName() {
return ownerName;
}
public boolean getIsDraft() {
return isDraft;
}
public boolean getIsQuickWalk() {
return isQuickWalk;
}
Based on this, I use this code to write to Firebase and it all works fine:
String key = mDatabaseRef.child(FIREBASE_ASSESSMENTS).push().getKey();
Assessment assessment = new Assessment(editCompanyText, editLocationText,
editIndustryText, editProductText, uid,
currentUser.getEmail(), isDraft, isQuickWalk, null);
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/" + FIREBASE_ASSESSMENTS + "/" + key,
assessment);
mDatabaseRef.updateChildren(childUpdates);
However, when I try to read from the database I believe this is where the problem lies:
FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder> adapter;
mRecyclerView = (RecyclerView) findViewById(R.id.draft_recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
Query query = mEvalRef;
FirebaseRecyclerOptions<Assessment> options = new FirebaseRecyclerOptions.Builder<Assessment>()
.setQuery(query, Assessment.class)
.build();
adapter = new FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder>(options) {
#Override
protected void onBindViewHolder(ViewDraftsViewHolder holder, int position, Assessment model) {
if(model.getIsDraft()) {
holder.companyName.setText(model.getCompanyName());
holder.industryName.setText(model.getIndustryName());
holder.locationName.setText(model.getLocationName());
holder.productName.setText(model.getProductName());
holder.ownerName.setText(model.getOwnerName());
if(model.getIsQuickWalk()) {
holder.isQuickWalk.setText("Quick Walkthrough");
} else {
holder.isQuickWalk.setText("Full Questionnaire");
}
}
}
#Override
public ViewDraftsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.completed_and_drafts_list_item, parent, false);
return new ViewDraftsViewHolder(view);
}
};
mRecyclerView.setAdapter(adapter);
private static class ViewDraftsViewHolder extends RecyclerView.ViewHolder {
TextView companyName;
TextView industryName;
TextView locationName;
TextView productName;
TextView ownerName;
TextView isQuickWalk;
public ViewDraftsViewHolder(View itemView) {
super(itemView);
companyName = (TextView) itemView.findViewById(R.id.companyView);
industryName = (TextView) itemView.findViewById(R.id.industryView);
locationName = (TextView) itemView.findViewById(R.id.locationView);
productName = (TextView) itemView.findViewById(R.id.productView);
ownerName = (TextView) itemView.findViewById(R.id.ownerName);
isQuickWalk = (TextView) itemView.findViewById(R.id.isQuickWalkView);
}
}
I'm not exactly sure where I'm going wrong that the FirebaseRecyclerAdapter is unable to convert the data back to an Assessment Object. Did i not set the object up correctly? Did I not set the RecyclerAdapter up correctly? This is how the data looks in Firebase
"-KzB39l1KH6MyEsgr6Ke" : {
"companyName" : "testing ",
"industryName" : "at",
"isDraft" : true,
"isQuickWalk" : true,
"locationName" : "five fifteen",
"ownerName" : "test#email.com",
"productName" : "please ignore"
},
any help you can give me would be excellent, I have been struggling with wrapping my head around this for a few days. Thanks!!
At this line:
Query query = mEvalRef;
I assume mEvalRef is a database reference, can you show it because its not clear how you query the data from the database.
just add (mEvalRef), in order to find the problem.
Edit
in your (Assessment) class , I noticed that there is no setter methods for the variable, add setter for each variable in the class and see if this helps.
EDIT 2
in your code where you try to read the values.
remove this
FirebaseRecyclerOptions<Assessment> options = new FirebaseRecyclerOptions.Builder<Assessment>()
.setQuery(query, Assessment.class)
.build();
and in this line or part of the adapter initialization:
adapter = new FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder>(options)
remove the (options) parameter and change the above line of code to this:
adapter = new FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder>(Assessment.class, R.layout.completed_and_drafts_list_item, ViewDraftsViewHolder.class, query )
next remove this code:
#Override
public ViewDraftsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.completed_and_drafts_list_item, parent, false);
return new ViewDraftsViewHolder(view);
}
and finally change the (private) to (public) in this:
private static class ViewDraftsViewHolder extends RecyclerView.ViewHolder {
and don't forget to keep the setters for variables in assessment class and make the variables public as I told you.
EDIT 3
now forget about EDIT 2 and retype your code the way you originally did it and just do this after you configured everything:
in the method where you initialize the adapter, add before this:
mRecyclerView.setAdapter(adapter);
this:
adapter.startListening();
I'm unable to retrieve the data which is nested inside "Leagues" and "Season".
In the database below, I cannot retrieve Season 2016/2017 points and results.
I am able to access the data that is not nested, such as Email and Username without problems
"Users" :
"User1" : {
"Email" : "dfs#sdf.com",
"Last_login" : "5:15pm",
"Username" : "Test",
"Leagues" : {
"FootballLeague" : true,
"CricketLeague" : true
},
"Season" : {
"2017" : {
"Points" : 5,
"Results" : 2
"newdata" : {
"randomdata1: data1",
"randomdata2: data2"
},
}
"2018" : {
"Points" : 7,
"Results" : 2
}
}
The following class is what I'm using to store data as objects:
public class Users {
private String Username;
private String Email;
private String Last_login;
private Map<String, Boolean> Leagues;
private Map<String, thisSeason> Season;
public Users() {
}
//All getters and setters for the strings.
public Map<String, Boolean> get_joined_Leagues() {
return Leagues;
}
public void set_joined_Leagues(Map<String, Boolean> leagues) {
Leagues = leagues;
}
public Map<String, thisSeason> getSeason() {
return Season;
}
public void set_thisSeason(Map<String, thisSeason> season) {
Season = season;
}
public static class thisSeason {
private int Points;
private int Results;
private Map <String, thisNewData> newdata;
public thisSeason() {
}
public int getthisSeason_results() {
return Results;
}
public void setthisSeason_results(int resultsin) {
Results = resultsin;
}
public int getthisSeason_points() {
return Points;
}
public void setSeason_points(int Pointsin) {
Points = Pointsin;
}
public Map<String, thisNewData> getNewData() {
return newdata;
}
public void set_thisNewData(Map<String, thisNewData> newdata_in) {
newdata= newdata_in;
}
public static class thisNewData {
private String randomdata1;
private String randomdata2;
//Getters and Setters
}
Here is part of my Java class where I access the Database:
List<Users> usersList= new ArrayList<Users>();
DatabaseReference fbDB = FirebaseDatabase.getInstance().getReference();
fbDB.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Users C = ds.getValue(Users.class);
usersList.add(C);
System.out.println(C.getSeason().getthisSeason_points()); //ERROR occurs here - null object reference
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I get a null object reference error as shown in the code above.
Also, on a slight side note - I'm aware my implementation for getting Leagues is incorrect. How can I retrieve the keys instead?
The main problems that I found in your code:
First, your Leagues object:
Well, it should not be a custom object at all, if it stays in the current structure, but a Map. This is the map object - a collection which has a key, and a value, just like a child in the Realtime Database.
If a league name (=key) didn't have a true (=value) next to it - the names could have been stored in String variables, but this is not the case, because every child in the Realtime Database must have a value, and storing a "dummy" value next to a league name makes each league a part of a Map. This current "dummy" is a boolean, and that's why this will be the leagues' data type:Map<String, Boolean> leagues.
Second, your Season object:
You are confusing between one season and many seasons. Your child - "Season" actually stores a lot of seasons. Thats why this case will be similar to the one above - each season's time is the key and the season itself is the value.
Therefore, the User class's variables should be:
private String Username;
private String Email;
private String Last_login;
private Map<String,Boolean> Leagues;
private Map<String, Season> Seasons;