Get object with list from firebase on Android - android

I have a class for users
public class User {
#SerializedName("username")
private String userName;
#SerializedName("email")
private String email;
#SerializedName("bags")
private List<Bag> bags;
.
.
.
And I have this data in my firebase DB
Before I added the "bags" items, the object was created fine, I'm using this method for retrieving the user by the uid:
public void retrieveUserByUid(String uid, FirebaseRetrieveUserListener listener){
Query userQuery = dbReference.child(FirebaseChild.users.name()).child(uid);
final FirebaseRetrieveUserListener dataListener = listener;
userQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
dataListener.retrieveUserByUid(user);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
As I said, this worked without the "bags" item, when I put it, the error I'm getting is this.
com.google.firebase.database.DatabaseException: Expected a List while deserializing, but got a class java.util.HashMap
This happens when I try to do this
User user = dataSnapshot.getValue(User.class);
I've searched a lot about how to retrieve a list, but all I find is retrieving a single list object, not a "mixed" object with "single data" and a list.

As you error says, while deserializing it was expected a HashMap and not a List. Because Firebase is a NoSQL database, everything in Firbease is structured as pairs of key and value. So every node in Firebase is a Map. In order to solve this, change the bags from List to HashMap and your problem will be solved.
You can also try this:
GenericTypeIndicator<List<YourClass>> t = new GenericTypeIndicator<List<Message>>() {};
List<YourClass> messages = snapshot.getValue(t);

Try this :
#SerializedName("bags")
private Map<String,Bag> bags;

Related

How could I insert new data to array without key in Firebase

I have an existing array that I created locally and import to Firebase and my array looks like this.
These both elements are objects created that have some many information related to appointments.
Now i am trying to create a new element with the same form, for example:
2--
|__ And the object I have created in my app
I have only managed or eliminate the rest of the elements (with setValue(object))
Appointment newAppointment = new Appointment.Builder()
.fechacita(dateSelected)
.horacita(hourSelected)
.usertoken(mAuthManager.getCurrentUserId())
.oficina(centerSelected)
.build();
mDatabaseRef.child("LISTACITAS").setValue(newAppointment);
or create it with an ID that when recovering the data causes a crash in the application due to the deserialization of the objects that are not equal.
The Appointment object that I want to insert is
public class Appointment implements Parcelable {
private String fechacita;
private String horacita;
private Office oficina;
private String userID;
.....
}
The class is a normal Parcelable class that generates an object with her builder.
Please some help...
try this code
mDatabaseRef.push().setValue(incidentReportUser)
Write it this way (push() adds values instead of overriding).
Ans from here
UPDATE 1
if you want a series in key, not some random value, try this:
get the last key in the list using
Query dbQry = mDatabaseRef.orderByKey().limitToLast(1);
dbQry.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int key = Integer.parseInt(dataSnapshot.getKey());
//Increment the key and add the object here using the earlier method
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
}
I have not checked this as of now, but you could get the idea

Firebase user details are not retrieved in Android

I am storing user details 'firstname' and 'lastname' in UserNode. But when i want to retrieve that details then no data is being retrieved. I tried almost all solutions on the internet but nothing solved my problem. Here is my code for retrieving data of the current user:
FirebaseUser userr = FirebaseAuth.getInstance().getCurrentUser();
if (userr != null) {
String name = userr.getDisplayName();
Log.e("value", name);
}
but it says "println needs a message"
I also tried with this but nothing happened:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String acctname = (String)dataSnapshot.child("firstname").getValue();
Log.e("name", acctname);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
]1
Please help me I am stuck with it
You're reading a collection of user with a ValueEventListener. As the [Firebase documentation for reading lists with a value event](Listen for value events) explains:
While using a ChildEventListener is the recommended way to read lists of data, there are situations where attaching a ValueEventListener to a list reference is useful.
Attaching a ValueEventListener to a list of data will return the entire list of data as a single DataSnapshot, which you can then loop over to access individual children.
Even when there is only a single [child node], the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result.
So in your code:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String acctname = (String)childSnapshot.child("firstname").getValue();
Log.i("name", acctname);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
Using FirebaseUser:
FirebaseUser implements UserInfo and in UserInfo's getDisplayName() documentation says
Returns the user's display name, if available.
So, it is possible that FirebaseUser.getDisplayName() return null when display name is not set. In that case Log.e() receives null as message and therefore prints println needs a message
Using your own structure:
Instead of using type conversion use getValue(Class<T>) like so:
String acctname = dataSnapshot.child("firstname").getValue(String.class);
Please, read how to retrieve data from firebase. I think you have a problem because you don't have Class Model.
Your steps:
Create model UserModel with firstname and lastname field
Use listener (example from docs):
// Attach a listener to read the data at our posts reference
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Post post = dataSnapshot.getValue(Post.class);
System.out.println(post);
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
See other answers: How to retrieve data from one single userID Firebase Android and retrieving data from firebase android

null object reference while trying to retrieve Firebase class Android

I have a model class to store Firebase User information. Inside of the model class I have a HashMap to store all of the data inside. Once I have stored the data, the I push the Hashmap into the Firebase database. The values store fine, but I cannot access the values. Every time I try to access them, I get an error saying that I am attempting to invoke a virtual method on a null object reference.
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
// These two lines of code give the error.
User author = ChildSnapshot.child("profile").getValue(User.class);
String author_username = author.getUsername();
These give me the error. I am attempting to grab data from the child of the snapshot. Why is this giving me an error? Is there a better way to do this?
JSON Firebase snapshot:
Model class:
//TODO model class for the user. This way I can set the values for each user. I will be adding more values in the future.
public class User {
public HashMap<String, String> hashMap = new HashMap<String,String>();
public User() {
}
public User(String username) {
hashMap.put("username",username);
}
public String getUsername(){
return hashMap.get("username");
}
}
In case somebody else was struggling with this issue, I wanted to give an answer. Inside of my ChildEventListener, the profile is the key in this situation so when I use ChildSnapshot.child("profile").getValue(User.class) it returns a null value. Also, (I'm not quite sure why this is) the value of the username was stored in a different class called User_message which was used to store the message. so my updated code looks something like this:
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
User_message author = ChildSnapshot.getValue(User_message.class);
String author_username = author.getUsername();
I was facing the same problem and spent more than 5 hours. I added Default Constructor of the model and this solves my problem.
public class User {
public String email;
public String name;
public User() {
}
public User(String email, String name) {
this.email = email;
this.name = name;
}}
I hope this will help you. Thanks

Firebase nested value

I am trying to query items in my firebase database based on an attribute value.
Here is my structure:
Here is my POJO object:
public class LapTime {
private int vehicleType;
private String track;
private String user;
private int time;
}
And here is my query code:
mDatabase.child("lap-time").orderByChild("track").equalTo(mTrackUuid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
time = dataSnapshot.getValue(LapTime.class).getTime() + "ms");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
My problem is that the datasnapshot I get back has for root lap-time and not the UUID, thus the getValue(LapTime.class) give me an empty object...
Here is the datasnapshot I get:
DataSnapshot { key = lap-time, value = {-KXwSxD0GYVC6awV8abw={track=-KXwSxCeV2Ib4Gt4pvjy, time=105000, vehicle-type=0, user=ZQKwPfRF0mVL5jAO7FaSPcsF7t42}} }
And this is what I would like to get:
DataSnapshot { key = -KXwSxD0GYVC6awV8abw, value ={track=-KXwSxCeV2Ib4Gt4pvjy, time=105000, vehicle-type=0, user=ZQKwPfRF0mVL5jAO7FaSPcsF7t42}} }
How can I do that?
Since your query code can actually have more than one result you should be calling dataSnapshot.getChildren() and iterating through the children to get the result you're looking for. Particularly, mDatabase.child("lap-time").orderByChild("track").equalTo(mTrackUuid) is a query that could have multiple results since there could be a situation where multiple LapTime objects could have a track that points to the same mTrackUuid. Now, to get the result of the log you posted you need to construct a the query like so: mDatabase.child("lap-time").child("-KXwSxD0GYVC6awV8abw"). Notice how the orderByChild/equalTo queries are gone since those result in a conditional query that may return a list of data instead of a singular value.

Getting the relevant key from ValueEventListener

I'm building an app that is basically a table for soccer that updates every time I change it in my DB.
I'm using Firebase in this way:
I'm trying to use an addValueEventListener, but I don't know which one of the values is the one that changes (dif,score,points...) therefore I don't which field in my table I should update.
public class table extends AppCompatActivity {
Button insert;
TextView name, games, win, lost, tie, score, dif, points;
Team A;
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference FootballRef = mRootRef.child("Football");
DatabaseReference HouseARef = FootballRef.child("HouseA");
protected void onStart() {
super.onStart();
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
String key = dataSnapshot.getKey() ;
Toast.makeText(table.this,key, Toast.LENGTH_SHORT).show();
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
// ...
}
};
HouseARef.addValueEventListener(postListener);
}
}
See here, when let's say I'm updating the name of housaA, I want to get back the key that got updated (in my case, name), but when I'm using
dataSnapshot.getKey() the Toast I'm getting back is HouseA and not name.
You won't be able to do this using a valuelistener.
Instead put a childeventlistener on the houseA.
Now inside onChildChanged, you should get the child node under houseA which has changed as a datasnapshot and from this snapshot, you can get the key which has changed

Categories

Resources