Retrieve data from Firebase into an entity - java

I'm trying to retrieve data from Firebase database to add it to local database.
This code :
database = FirebaseDatabase.getInstance();
myRef = database.getReference();
Query LANGUAGES_REF = myRef.child("languages").orderByChild("id");
LANGUAGES_REF.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (dataSnapshot.hasChildren()) {
Iterator<DataSnapshot> iterator = dataSnapshot.getChildren().iterator();
do {
Language language = iterator.next().getValue(Language.class);
languageR.insert(language);
} while (iterator.hasNext());
}
is not working , and I know it's because Language.class is an entity.
Is there a way other than creating a new class with getters and setters and full constructor ... and repeating everything??
The error I got was:
com.google.firebase.database.DatabaseException: Can't convert object
of type java.lang.Long to type
com.android.android.Database.Entities.Language
at this line :
Language language = iterator.next().getValue(Language.class);
Thanks
edit:
firebase database structure
"languages" : {
"LHZ7cAeOdPn-LwHNjIk" : {
"id" : 1,
"langName" : "Russian"
},
"LHZ7cAtXTGBlnWsdQOd" : {
"id" : 2,
"langName" : "French"
},
"LHZ7cAvrRs0rgI-PaJd" : {
"id" : 3,
"langName" : "Turkish"
}
}
language.class
import java.io.Serializable;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
#Entity
public class Language implements Serializable {
#PrimaryKey(autoGenerate = true)
private int id;
private String langName;
public int getId() {
return id;
}
public String getLangName() {
return langName;
}
public Language(String langName) {
this.langName = langName;
}
public void setId(int id) {
this.id = id;
}
}

To solve this, you need to remove the do-while loop because there is no need to iterate using getChildren() method, you can get the data directly from the dataSnapshot object like this:
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Language language = dataSnapshot.getValue(Language.class);
languageR.insert(language);
Log.d(TAG, language.getLangName());
}
The output in your logcat will be:
Russian
French
Turkish

Related

In Firebase and Java, how to get value from datasnapshot correctly?

Recently I use Firebase in my Android application and try to get used of NoSQL data structure but I met some problems.
First, my data structure is very simple:
{
"user": {
"userid1" :{
"id: "userid1"
"name": "Samantha",
"age": 25
"email" : "abc#gmail.com"
}
}
}
So I wrote my Entity class like this
public class User implements Serializable {
private String id;
private String name;
private int age;
private String email;
}
When I want to get all user into list:
FirebaseDatabase.getInstance().getReference("user").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot : snapshot.getChildren()){
User user = dataSnapshot.getValue(User.class);
listUser.add(user);
}
}
}
But if I want to change my data structure like this, I don't know how to do the same:
{
user: {
userid1 :{
id: "userid1"
name: "Samantha",
age: 25
email : "abc#gmail.com"
posts:{
postid1: {
postid : "postid1"
content : "content1"
}
postid2: {
postid : "postid2"
content : "content2"
}
}
}
}
}
I figure I have to create a Post entity class but how can I fetch list of user like before? Anyone can explain to me would be helpful.
Nesting data like you want to do is an anti-pattern in Firebase, and goes against the recommendations in the documentation on data structuring. See https://firebase.google.com/docs/database/android/structure-data#best_practices_for_data_structure
That said: if you have a structure like this, you can read it by adding posts map to the class to read its data:
public class User implements Serializable {
public String id;
public String name;
public int age;
public String email;
public Map<String, Object> posts;
}
If you want to get them type-safely, you might need to use a GenericTypeIndicator.

How to get out the stored data from Firebase?

I'm not getting the output from Firebase database. It's not returning anything. Here is my data structure.
I also tried getting value through query but it returned database error:
Cannot convert java.util.hashmap to String
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference().child("Member").push();
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String value = ds.getValue(String.class);
Log.d("Tag", "Value is" + value);
}
}
JSON:
{
"Member" : {
"-LhKJVG1Tj2628sHPg4D" : {
"age" : "21",
"name" : "Gagan",
"nickname" : "Gaggi"`enter code here`
},
"-LhKKaNFnPrrh1bQNPfH" : {
"age" : "18",
"name" : "Jashan",
"nickname" : "Jassi"
}
}
}
You cannot call getValue with String.class because it does not meet the criteria of the method call.
From the documentation
public T getValue(Class valueType)
This method is used to marshall the data contained in this snapshot into a class of your choosing. The class must fit 2 simple constraints:
The class must have a default constructor that takes no arguments
The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized
An example class might look like:
class Message {
private String author;
private String text;
private Message() {}
public Message(String author, String text) {
this.author = author;
this.text = text;
}
public String getAuthor() {
return author;
}
public String getText() {
return text;
}
}
// Later
Message m = snapshot.getValue(Message.class);
You can use String class
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name= ds.child("name").getValue(String.class);
String age= ds.child("age").getValue(String.class);
//and similar for others
Log.d("TAG", email + " / " + name);
}
}

Firebase Android getValue(class) doesn't work

So this is my bind model class:
public class UserBanknoteAmountBindModel {
public String id;
public String userId;
public String banknoteType;
public String banknoteAmount;
public UserBanknoteAmountBindModel(){
}
public String getBanknoteAmount() {
return banknoteAmount;
}
public String getBanknoteType() {
return banknoteType;
}
public String getUserId() {
return userId;
}
public void setBanknoteAmount(String banknoteAmount) {
this.banknoteAmount = banknoteAmount;
}
public void setBanknoteType(String banknoteType) {
this.banknoteType = banknoteType;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
(idk if acess modifiers matter in this case).
I am trying to parse my data:
for (DataSnapshot banknoteAmount:dataSnapshot.getChildren()){
UserBanknoteAmountBindModel userBanknoteAmountBindModel=dataSnapshot.getValue(UserBanknoteAmountBindModel.class);
Log.wtf("hgfh", banknoteAmount.getValue().toString());
}
I see that I am receiving my data because I can log it.
{banknoteAmount=3, banknoteType=20_dollar,
userId=112371098270685247195}
Anyway my data doesn't get inside my bind model. I read somewhere that I need not only to provide getters but also setters (that's why I put those setters PS: Is the thing for the setters true?).
Any ideas?
EDIT: Database Structure https://i.stack.imgur.com/o5Hgp.png
PS: The problem was that I was using the parameter from another function for the getValue (not the foorloop variable)
To get the values of banknoteAmount, banknoteType and userId, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userBanknoteAmountRef = rootRef.child("userBanknoteAmount");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
UserBanknoteAmountBindModel userBanknoteAmountBindModel = ds.getValue(UserBanknoteAmountBindModel.class);
String banknoteAmount = userBanknoteAmountBindModel.getBanknoteAmount();
String banknoteType = userBanknoteAmountBindModel.getBanknoteType();
String userId = userBanknoteAmountBindModel.getUserId();
Log.d("TAG", banknoteAmount + " / " + banknoteType + " / " + userId);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
userBanknoteAmountRef.addListenerForSingleValueEvent(valueEventListener);
The output will be:
3 / 20_dollar / 112371098270685247195
When you are using the following line of code:
banknoteAmount.getValue().toString()
You are actually printing the String representation of banknoteAmount.getValue() which has as a return value a Map object which contains those three values.

Android - unable to add data to arraylist of string - when data retrieved from firebase

I have a custom list adapter that has many methods that query the database and add data to different java objects or lists.
code to consider in adapter as follows: -
static class ViewHolder {
ArrayList<String> imgUrls;
//other variables;
}
then initiated it in getView method as:-
public View getView(#params) {
holder.imgUrls = new ArrayList<>();
}
//i have a method that query and retrieve data from firebase as follows:-
public void getPhoto(final ViewHolder holder) {
Query query = reference
.child(mContext.getString(R.string.dbname_collections))
.child(holder.collection.getCollection_id())
.child("photo_url");
query.keepSynced(true);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) {
imgUrl = singleSnapshot.getValue(String.class);
Log.d(TAG, "onDataChange: imgUrl: " + imgUrl);
holder.imgUrls.add(imgUrl);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Log.d(TAG, "getPhoto: list with values " + holder.imgUrls);
}
My database in firebase console look like this:-
{
"collections": {
"-L9nNSyF7ZhEqpvmPo0Z": {
"caption": "jakhaha",
"collection_id": "-L9nNSyF7ZhEqpvmPo0Z",
"date_created": "2018-04-11T11:55:57Z",
"photo_url": [
"https://firebasestorage.googleapis.com/v0/b/backbench-72a47.appspot.com/o/collection%2Fusers%2FHb8ORoozQ3WhyxjaSyqazjHypkf2%2F2018-04-11T11%3A55%3A57Z%2Fphoto0?alt=media&token=08fdb740-9b16-455b-83ec-bfcec1455834",
"https://firebasestorage.googleapis.com/v0/b/backbench-72a47.appspot.com/o/collection%2Fusers%2FHb8ORoozQ3WhyxjaSyqazjHypkf2%2F2018-04-11T11%3A55%3A57Z%2Fphoto1?alt=media&token=eeca4b10-0729-4ca9-be18-c31d054add19",
"https://firebasestorage.googleapis.com/v0/b/backbench-72a47.appspot.com/o/collection%2Fusers%2FHb8ORoozQ3WhyxjaSyqazjHypkf2%2F2018-04-11T11%3A55%3A57Z%2Fphoto2?alt=media&token=b33c97b0-c2bf-4199-bef0-b498f505a678"
],
//this are the imageUrls i want to retrieve as a arrylist
"tags": "#NoTags",
"user_id": "Hb8ORoozQ3WhyxjaSyqazjHypkf2"
}
}
}
in my firebase model class :-
public class Collection implements Parcelable {
//properties for photo (*case sensitive*)
private String caption;
private String date_created;
private String collection_id;
private String user_id;
private String tags;
//list of likes
private List<String> photo_url;
private List<Like> likes;
private List<Comment> comments;
public Collection() {
}
//constructor..getter setters etc...
}
in my log console i see that values of imgUrl are fatched
04-11 20:35:03.992 21269-21269/com.backbenchers.administrator.instaclone D/CollectionListAdapter: onDataChange: imgUrl://url of image 1
onDataChange: imgUrl: url of image 2
onDataChange: imgUrl: ...image 3
but it shows list as null or [] :-
D/CollectionListAdapter: getPhoto: list is with values : []
"I want to fetch this firebase data and add it to an arraylist.."
what is wrong ??
Thanks!

Firebase Database - Unable to retrieve nested data

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;

Categories