null object reference while trying to retrieve Firebase class Android - 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

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 serialization names

I created an object to send some data to firebase. As an example, I use firebase user example:
public class User {
public String username;
public String email;
public User() {
// Default constructor required for calls to DataSnapshot.getValue(User.class)
}
public User(String username, String email) {
this.username = username;
this.email = email;
}
}
I want to encode property names that are sent to firebase. Currently keys are sent using variable names. I want to encode keys something like Useraname and Email, like Gson is doing. I don't want to change variable names.
#SerializateName("Username")
public String username;
#SerializateName("Username")
public String email;
I used #SerializateName(), but is not working. Same with #PropertyName that is used by Firebse, is not working. What I can use in order to serializare custom keys?
Update 1
public class Pojo {
#PropertyName("Guid")
public String guid;
#PropertyName("Name")
public String name;
public String getPojoGuid() {
return guid;
}
public void setPojoGuid(String guid) {
this.guid = guid;
}
}
As you can see in the image, it saves keys based on variable names. I changed property name from annotation for one field and when i save it, it ignores it, but when i change variable name, it save as new entry with key for that new varialbe name.
In this documentation is a method toMap(). If i do like that, is working (is not convenient for me), but is not working with #PropertyName.
Update 2
If i mark getters and setters with #Exclude and class with #IgnoreExtraProperties is working. I don't have to use toMap() method example from documetation. Is using specified name from #PropertyName. Not a good thing in my opinion, create confuses.
The Firebase SDK uses the annotation it finds for the property whenever it gets or sets its value. That means you need to consider how Firebase gets/sets the value, and annotate each place it looks.
Since you're declaring a getter method, Firebase will use that to get the value of the property. It will use the field for setting the value. So the annotation needs to be on both:
public class Pojo {
#PropertyName("Guid")
public String guid;
#PropertyName("Name")
public String name;
#PropertyName("Guid")
public String getPojoGuid() {
return guid;
}
#PropertyName("Guid")
public void setPojoGuid(String guid) {
this.guid = guid;
}
}
If you'd have getters and setters, the annotation would need to be on those, but not on the fields anymore:
public class Pojo {
private String guid;
private String name;
#PropertyName("Guid")
public String getPojoGuid() {
return guid;
}
#PropertyName("Guid")
public void setPojoGuid(String value) {
guid = value;
}
#PropertyName("Name")
public void setPojoGuid(String guid) {
this.guid = guid;
}
#PropertyName("Name")
public void setPojoGuid(String value) {
name = value;
}
}
What you are looking for is the feature of SDK Version 9.2 in which you can now use a new #PropertyName attribute to specify the name to use when serializing a field from a Java model class to the database. This replaces the #JsonProperty attribute.
#PropertyName("Username")
public String username;
#PropertyName("Email")
public String email;
See also this post in which Frank van Puffelen explains very clearly this concept.
#PropertyName :
Marks a field to be renamed when serialized. link
you have to use #PropertyName with public fields and no need for getters/setters

Get object with list from firebase on 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;

Android: Search Query in Firebase

I am currently working on an Android project backed by FIREBASE. When I perform querying similar to select statement in SQL, it does not give me the intended result.
My FIREBASE database looks like this:
The code I've used is as follows:
ref = FirebaseDatabase.getInstance().getReference().child("DiscussionForumPosts");
ref.orderByChild("discussionName").equalTo(discussion_name_from_bundle)
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
DiscussionPostReadModel model = dataSnapshot.getValue(DiscussionPostReadModel.class);
}
//other predefined methods
}
discussion_name_bundle is a string variable that I get from the previous activity.
My DiscussionPostReadModel.java looks like this:
public class DiscussionPostReadModel {
public String discussionName, discussionMessage, userName;
public DiscussionPostReadModel(){}
public DiscussionPostReadModel(String discussionName, String discussionMessage, String userName){
this.discussionName = discussionName;
this.discussionMessage = discussionMessage;
this.userName = userName;
}
public String getDiscussionName(){
return discussionName;
}
public String getDiscussionMessage(){
return discussionMessage;
}
public String getUserName(){
return userName;
}
}
I actually need the system to fetch only the nodes whose discussionName equals the variable discussion_name_from_bundle. instead, it returns to me all the children found in discussionForumPost in the FIREBASE database.
Kindly help me do the functionality of retrieving only the children which satisfies the equality condition. Thank you in advance.
To only retrieve one result you need to also use the limitToFirst(wantedNumberOfResults) method.
You would implement it like this:
ref = FirebaseDatabase.getInstance().getReference().child("DiscussionForumPosts");
ref.orderByChild("discussionName").equalTo(DiscussionForumPosts).limitToFirst(1).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
DiscussionPostReadModel model = dataSnapshot.getValue(DiscussionPostReadModel.class);
}
//other predefined methods
}

Firebase - can't use setValue() on LHS of assignment?

I'm using Android Studio 1.5, and using the following code straight from the documentation itself
public class User {
private int birthYear;
private String fullName;
public User() {
}
public User(String fullName, int birthYear) {
this.fullName = fullName;
this.birthYear = birthYear;
}
public long getBirthYear() {
return birthYear;
}
public String getFullName() {
return fullName;
}
}
Firebase code
Firebase ref = new Firebase("https://docs-examples.firebaseio.com/android/saving-data/fireblog");
Firebase alanRef = ref.child("users").child("alanisawesome");
User alan = new User("Alan Turing", 1912);
alanRef.setValue(alan);
It throws an error cannot resolve symbol setValue. When I try the autocomplete feature, there's no suggestion for setValue(); however if used on the RHS of the assignment operation like in the code below, it works. Can someone help me out here?
Firebase abc = ref.setValue(); //seems to work
I have not seen your entire code but I am assuming that you tried using setValue outside a method. The setValue method can only be invoked inside a method.

Categories

Resources