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.
Related
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
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
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
}
Imagine I have a service to retrieve some authors (id, firstname, lastname, birthday, nationality) and a second service to retrieve an author's book (title, summary, number of pages).
I would like my network call to return me a list of authors with their books.
To illustrate, my services would return me AuthorOResponse and BookResponse and I would like to emit an Observable of AuthorObject.
public class AuthorResponse {
private String id;
private String firstname;
private String lastname;
private Date birthday;
private String nationality;
}
public class BookResponse {
private String title;
private String summary;
private int pageNumber;
}
public class AuthorObject {
private String id;
private String firstname;
private String lastname;
private Date birthday;
private String nationality;
private List<BookObject> books
}
My services would be something like
Observable<List<AuthorResponse>> getAuthors()
Observable<List<BookResponse>> getAuthorBooks(String authorId)
I would like to use them to emit an Observable but cannot figure out how to do it since each of my calls to getAuthorBooks need an author.
I came up with something looking like this but I have an issue since my concatMap make me "loose" my author.
myServices.getAuthors()
.map(author -> createAuthor())
.concatMap(author -> mWebService.getAuthorBooks(author.getId())
.flatMapIterable(data -> data.items)
.map(book -> addBook())
Does someone know how I could do this ?
You could use special flatMap overload designed for such cases:
myServices.getAuthors()
.map(author -> createAuthor())
.flatMap(author -> mWebService.getAuthorBooks(author.getId()),
(author, data) -> {
author.setBooks(data.items));
return Observable.just(author);
})
.toList() //here is your Observable<List<Author>>
Maybe something like this:
getAuthors.map(new Func1<List<AuthorResponse>, AuthorObject>() {
#Override
public AuthorObject call(List<AuthorResponse> authorResponses) {
return createAuthor();
}
}).flatMap(new Func1<AuthorObject, Observable<AuthorObject>>() {
#Override
public Observable<AuthorObject> call(final AuthorObject authorObject) {
return getAuthorBooks(authorObject.id)
.map(new Func1<List<BookResponse>, AuthorObject>() {
#Override
public AuthorObject call(List<BookResponse> bookResponses) {
authorObject.books = parseBooks(bookResponses);
return authorObject;
}
});
}
});
Query the Authors, map each AuthorResponse to AuthorObject, then using flatMap query books for each Author, and map it in order to add parsed books to the generated earlier AuthorObject.
at the end you'll get an Observable that emits AuthorObject with their books list populated.
I have a RealmObject Notes:
public class Notes extends RealmObject {
private String title;
private String text;
private Date updatedDate;
private RealmList<Notes> editHistories = new RealmList<>();
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public RealmList<Notes> getEditHistories() {
return editHistories;
}
public void setEditHistories(RealmList<Notes> editHistories) {
this.editHistories = editHistories;
}
}
I want to keep track of all the edits made to the Notes object. So, whenever someone edits the Note, I want the previous one to be stored in editHistories while I display the most recent. I tried it this way:
RealmResults<Notes> results = realm.where . . .;
Notes prevNote = results.get(0);
Notes newNote = realm.copyToRealm(prevNote);
newNote.getEditHistories().add(prevNote);
// set other parameters
And this way:
RealmResults<Notes> results = realm.where . . .;
Notes prevNote = results.get(0);
Notes newNote = realm.createObject(Notes.class);
//set other parameters
newNote.setEditHistories(prevNote.getEditHistories());
newNote.getEditHistories().add(prevNote);
prevNote.removeFromRealm();
But whenever I update newNote, the prevNote in editHistories gets updated too. Is there any way to clone prevNote such that it will be separate from newNote and won't be affected by any changes I make to the latter?
Any suggestions would be most welcome and appreciated!
copyToRealm() doesn't make a copy of objects already in the Realm. The copy part is a reference to the copying of objects not in Realm, but I can see why it can get slightly confusing and our Javadoc should probably specify the behaviour better.
One work-around you can use is to make sure the object is detached first, so like this:
RealmResults<Notes> results = realm.where . . .;
// This creates a detached copy that isn't in the Realm
Notes prevNote = realm.copyFromRealm(results.get(0));
// add() will automatically do a copyToRealm if needed
newNote.getEditHistories().add(prevNote);
I used the following code to clone in swift 3
Swift 3
To create a clone of user object in swift just use
let newUser = User(value: oldUser);
Note: The new user object is not persisted.