I want to obtain the values to show them in a recyclerview, I have tried in many ways but without fortune.
This is my firebase data.
"Users" : {
"X7aVfZH5oZbIaeyLm9FAjOSr5Gd2" : {
"images" : {
"urlImages1" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg1.jpg?alt=media&token=e26fd6a2-2be7-4a01-920e-0aed1fe06436",
"urlImages2" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg2.jpg?alt=media&token=40165918-3b46-4b22-b0ef-255965b7855d",
"urlImages3" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg3.jpg?alt=media&token=cfd7d00d-9b1a-44fd-80d4-a2947f7de743",
"urlImages4" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg4.jpg?alt=media&token=995419a7-70f7-4330-b046-d06a4d54453e",
"urlImages6" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg6.jpg?alt=media&token=ee6f566a-a9e5-4e8f-9d53-64d3f3bc97a6",
"urlImages7" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg7.jpg?alt=media&token=883a3321-fbba-49bd-aae3-14b005b4cc5b"
},
"locations" : {
"locations1" : "14.2830817 -89.7263953",
"locations2" : "14.2661424 -89.7220017",
"locations3" : "14.2846352 -89.7251991",
"locations4" : "14.2684987 -89.7266704",
"locations5" : "14.2684987 -89.7266704",
"locations6" : "14.2684987 -89.7266704",
"locations7" : "14.2684987 -89.7266704"
}
I want to get the data from "images" and "locations".
imageRef = database.getInstance().getReference("Users").child(userid);
imageRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot mData : dataSnapshot.getChildren()) {
String mImages = mData.child("images").getValue(String.class);
String mLocations = mData.child("locations").getValue(String.class);
ItemData itemData = new ItemData();
itemData.setImages(mImages);
itemData.setLocations(mLocations);
data.add(itemData);
}
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
What I try to do is show the image and the location in a recyclerview. The "images" key contains url1, url2, url3... in the same way the "locations" key and I want to show them together in the adapter.
Please look at the image of the link
You use this code to get the data from images:
String mImages = mData.child("images").getValue(String.class);
But if we look at your JSON, the images property looks like this:
"images" : {
"urlImages1" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg1.jpg?alt=media&token=e26fd6a2-2be7-4a01-920e-0aed1fe06436",
"urlImages2" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg2.jpg?alt=media&token=40165918-3b46-4b22-b0ef-255965b7855d",
"urlImages3" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg3.jpg?alt=media&token=cfd7d00d-9b1a-44fd-80d4-a2947f7de743",
"urlImages4" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg4.jpg?alt=media&token=995419a7-70f7-4330-b046-d06a4d54453e",
"urlImages6" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg6.jpg?alt=media&token=ee6f566a-a9e5-4e8f-9d53-64d3f3bc97a6",
"urlImages7" : "https://firebasestorage.googleapis.com/v0/b/anthiefy.appspot.com/o/X7aVfZH5oZbIaeyLm9FAjOSr5Gd2%2FImages%2FImg7.jpg?alt=media&token=883a3321-fbba-49bd-aae3-14b005b4cc5b"
},
That is an entire JSON object, not merely a string. So you call will return null, since the value is not a string.
To get all image URLs from this JSON, you will need to loop over its child nodes and get the individual values from there:
for (DataSnapshot imageSnapshot: mData.child("images").getChildren()) {
System.out.println(imageSnapshot.getValue(String.class));
}
Since there can be (and are) multiple images and locations, either your ItemData will need to handle those, or you will need to select a single image and location, or you will have to convert all images/locations into a single string.
Related
I want to include surname inside that unique key together with full name and student id. I am quite stuck and this is probably my last resort. I don't know what to do in the coding. Your answer will definitely a big help. Thank you so much!
{
"Students" : {
"-Ma9R58DvoFMkLqukMmk" : {
"fullname" : "Juan Capistrano Dela Cruz",
"studId" : "18-ln-0001"
},
"-Ma9TttvUqShhYjD-q_5" : {
"fullname" : "Maria Acosta Gomez",
"studId" : "18-ln-0002"
},
"-Ma9Ub__33IsWEFDbitu" : {
"fullname" : "David Orosco Villar",
"studId" : "18-ln-0003"
},
"-Ma9ZI_FvEgutnSvsSrU" : {
"fullname" : "Ara Quizon Diaz",
"studId" : "18-ln-0006"
},
"-MaBPU-fsEInFUGWft_n" : {
"surName" : "Diaz"
}
}
}
DatabaseReference databaseReference =
FirebaseDatabase.getInstance().getReference();
String userId = databaseReference.child("Students").push().getKey();
String surname = snameInput.getText().toString();
HashMap hashMap = new HashMap();
hashMap.put("surName", surname);
databaseReference.child("Students").child(userId).setValue(hashMap).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(PersonalData.this, "Surname updated", Toast.LENGTH_SHORT).show();
}
});
If you know the student ID of the node you want to update, then you can take a two-step process:
Use a query to find the nodes with that student ID.
Update that node/those nodes.
In code that'd be:
Query query = databaseReference.child("Students").orderByChild("studId").equalTo("18-ln-0002");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot resultSnapshot) {
for (DataSnapshot studentSnapshot: resultSnapshot.getChildren()) {
studentSnapshot.getRef().child("surname").setValue("Cortez");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
In general though, if your student IDs are already unique, then it makes more sense to use those as the keys for the nodes under Students. So in that case you'd add a student with:
HashMap hashMap = new HashMap();
hashMap.put("fullname", "Maria Acosta Gomez");
databaseReference.child("Students").child("18-ln-0002").setValue(hashMap);
And updating them would then be as simple as:
databaseReference.child("Students").child("18-ln-0002").child("surname").setValue("Cortez");
Or if you want to use the hashmap:
HashMap hashMap = new HashMap();
hashMap.put("surName", snameInput.getText().toString());
databaseReference.child("Students").child("18-ln-0002").updateChildren(hashMap);
I want to get child of node using addValueEventListener(). when books data is few, it works properly but when books count is more than 30000 it gives error as "java.lang.RuntimeException: Firebase Database encountered an OutOfMemoryError. You may need to reduce the amount of data you are syncing to the client (e.g. by using queries or syncing a deeper path)."
Firebase data structre is as
booksData
123 (book id)
bookname : ""
writer : ""
price : ""
category : ""
publicher : ""
...
456 (book id)
bookname : ""
writer : ""
price : ""
category : ""
publicher : ""
...
.... and so on. having vast data
(Data structure & name is changed just for sample)
I tried in android as
userIDRef1.child("booksData").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Log.e(TAG, "in get booksData");
ArrayList<BooksWrapper> booksList = new ArrayList<>();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
BooksWrapper vtw = postSnapshot.getValue(BooksWrapper.class);
booksList.add(vtw);
}
userIDRef1.child("booksData").removeEventListener(this);
Log.e(TAG, "daybooks data size is : "+booksList.size());
if (booksList.size() >0){
db.addBookData(booksList);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read app title value.", error.toException());
}
});
is there any way to get data in chunks as first 1000 books then next 1000 & so on...? Any solution please...
I'm trying to develop a simple application to learn firebase database.
Here is my realtime database schema
mydirectory
-contact_list
-LOyDhepB_IZlM6lZtko
mobileNumber: "9385746982"
name: "Jay"
-LOyDhetiPHalLhXrOaU
mobileNumber: "8000478912"
name: "Ravi"
-LOyDhetiPHalLhXrOaV
mobileNumber: "123456789"
name: "ABC"
-LOyDheubruATyyBp8dG
mobileNumber: "023456879"
name: "XYZ"
I want to get the list of data ordered by name
So I'm using this snippet to load the data in my android application
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("contact_list").orderByChild("name").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> objectMap = (HashMap<String, Object>) dataSnapshot.getValue();
Master.personList.clear();
for (Object obj : objectMap.values()) {
if (obj instanceof Map) {
Map<String, Object> mapObj = (Map<String, Object>) obj;
String name = (String) mapObj.get("name");
String mobileNumber = (String) mapObj.get("mobileNumber");
Person person = new Person(name, mobileNumber);
Master.personList.add(person);
populateListView();
}
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w("ANDs", "Failed to read value.", error.toException());
}
});
But it does not sort data based on the alphabetical order of name
key. Am I doing anything wrong or missing something?
P.S.
I've also indexing rules (ref), but still result is same! It doesn't sort data alphabetical wise.
{
"rules": {
"mydirectory": {
"contact_list": {
"$user_id": {
".indexOn": ["name"]
}
}
},
".read": true,
".write": true
}
}
I've tried many things from other posts like this topic but nothing works! Please don't make it duplicate instead please help me to solve it!
A HashMap can only contain a key and a value. And the keys in a Map are by definition not ordered. So when you call dataSnapshot.getValue(), you're throwing away all ordering information.
To maintain the order, you'll need to loop over dataSnapshot.getChildren():
public void onDataChange(DataSnapshot dataSnapshot) {
Master.personList.clear();
for (DataSnapshot contactSnapshot: dataSnapshot.getChildren()) {
String name = contactSnapshot.child("name").getValue(String.class);
String mobileNumber = contactSnapshot.child("mobileNumber").getValue(String.class);
Person person = new Person(name, mobileNumber);
Master.personList.add(person);
}
populateListView();
}
You'll also notice that I use child(...) to get a child snapshot for a specific property and get the String value from it. Your approach for that would work too, but I find that I get better error messages when I stick to a snapshot longer (instead of converting to a Map).
I'm trying to retrieve a set of restaurant menu data grouping them according to menu category and create list of menu items for each menu category and create a HashMap of these lists with a key of category.
The below JSON tree displays how I'm storing the menu items for each restaurant under a restaurant ID.
"Menu" : {
"C39Jv1oVVdXbQdyCOcTQZyZnmC3x" : { //Restaurant ID
"applepie" : {
"item_category" : "Desserts",
"item_name" : "Apple Pie",
"item_price" : "280"
},
"chocopudding" : {
"item_category" : "Desserts",
"item_name" : "Chocolate Pudding",
"item_price" : "320"
},
"friedrice" : {
"item_category" : "Main Courses",
"item_name" : "Fried Rice",
"item_price" : "250"
},
"seafoodrice" : {
"item_category" : "Main Courses",
"item_name" : "Sea Food Fried Rice",
"item_price" : "300"
}
}
}
The categories of food each restaurant is stored in MenuCategories node
"MenuCategories" : {
"C39Jv1oVVdXbQdyCOcTQZyZnmC3x" : { //Restaurant ID
"Desserts " : true,
"Main Courses" : true
}
}
What I'm trying to achieve according to the above data-set is something like :
List1 :(menu,menu) //Desserts
List2 :(menu,menu) //Main Courses
Here's my attempt (minus the part of creating lists and Hashmap to keep the code short):
Database references for both nodes:
mDatabase = FirebaseDatabase.getInstance().getReference().child("Menu").child(res_id);
mMenuCategoryRef = FirebaseDatabase.getInstance().getReference().child("MenuCategories").child(res_id);
Data retrieval :
List<String> menuCatList = new ArrayList<>();
mMenuCategoryRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot data : dataSnapshot.getChildren()){
menuCatList.add(data.getKey()); //adds all the categories to array list
}
for(String menuCat : menuCatList){
//I'm trying to retrieve items under each category
mDatabase.orderByChild("item_category").equalTo(menuCat).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot data : dataSnapshot.getChildren()){
System.out.println("MenuListWithCat "+data.getKey()+" - "+data.getValue());
}
}
.....
According to my code, I'm only receiving items with category "Main Courses", this is what my println prints.
`System.out.println("MenuListWithCat "+data.getKey()+" - "+data.getValue());`
MenuListWithCat friedrice - {item_name=Fried Rice, item_category=Main Courses, item_price=250}
MenuListWithCat seafoodrice - {item_name=Sea Food Fried Rice, item_category=Main Courses, item_price=300}
It completely skips over "Desserts" category, why is that?
Any assistance regarding this would be very helpful.
I was able to figure it out. I was complicating my Firebase data retrieval process in order to make separate lists of menu items for each category, I decided to retrieve all menu items and add it to an ArrayList without considering their category types, like below:
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
Menu menu = child.getValue(Menu.class);
menuList.add(menu);
}
And then group all menu items according to their category and added them to separate lists using a bit of Java logic, which gives me a HashMap of the following format:
Map<ItemCategory, ListofItems>
Here's the logic:
Map<String, List<Menu>> menuMap= new HashMap<String, List<Menu>>();
for(Menu menuItem : menuList){
List<Menu> tempList = menuMap.get(menuItem.getItem_category());
if(tempList == null){
tempList = new ArrayList<Menu>();
menuMap.put(menuItem.getItem_category(), tempList);
}
tempList.add(menuItem);
}
And I removed the MenuCategories node from the database which was not needed, as Frank mentioned in the comments.
I hope this would help someone in the future! :)
Special thanks #Frank for valuable feedback and support.
I have stored my Images URLs on Firebase Database, as I have been reading here it was the way to go.
Now I need to retrieve the 5 Picture Objects form the List and put them into an array for later use.
So I add a SingleValueEvent to my Reference which is on UserId Node and get a DataSnapshot Object, which I check for null.
The problem is that even if I only have a list of 5 Pictures in my Database, when iterating on the DataSnapshot Object it adds 19 Picture Objects into the Array...
02-14 15:13:45.375 21952-21952/com.example I/EditProfileFragment:Picture Array : 19
What am I missing here?
The Json looks like this:
PicturesUrls {
UserID {
randomID{
pictureName : "Main Picture"
pictureUrl : "URL"
}
randomId
pictureName : "Second Picture"
pictureUrl : "URL"
randomId {
pictureName : "Third Picture"
pictureUrl : "URL"
}
}
}
Here is my Code:
ArrayList<Object> mPicturesArray = new ArrayList<>();
....
....
mPicturesUrlRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null) {
addPicturesToArray(dataSnapshot);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
private void addPicturesToArray(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
Picture picture = child.getValue(Picture.class);
mPicturesArray.add(picture);
Log.i(LOG_TAG, "One Picture added : " + picture.getPictureName());
}
Log.i(LOG_TAG, "Picture Array : " + mPicturesArray.size());
}
Hummm....
Ok so I have changed the ArrayList to a HashMap and things are working as expected now.
No idea why but...