I am trying to get the root of the Firebase with nested children which are ordered by keys. My data structure is like this:
"-Ka3rbdLvH0I8X1Lg4of" : {
"menus" : {
"-KaD6U8_n5CPbRmAhgM2" : {
"menuItems" : {
"-KaD6UEoDvrm1W1a55AR" : {
"name" : "Annemin Kahvaltısı"
},
"-KaD6UKf0DyPja-Rni0X" : {
"name" : "Sıcak Kahvaltı",
},
"-KaD6UQyrJ1p5Ok9oya4" : {
"name" : "Anadolu Kahvaltısı",
},
"name" : "Sahanda Ürünler"
},
"-KaD6VgvHIj37Qyrirw1" : {
"menuItems" : {
"-KaD6Von-sz1xqPLeI5I" : {
"name" : "Sade Omlet",
},
"-KaD6Vvg0cOBFuABbtuU" : {
"name" : "Mantarlı Omlet",
},
"name" : "Omletler"
},
I have a restaurant -> menus -> menuItems. A restaurant can have multiple menus and a menus can have multiple menuitems. They inserted with specific Firebase keys. The code, I am getting the data as
mDatabase.child("restaurants").child(lastResIdFirebaseKey).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
currentRest = snapshot.getValue(Restaurant.class);
tv_resName.setText(currentRest.getName());
tv_resDesc.setText(currentRest.getAddress());
iv_resImage.setImageResource(R.drawable.default_restaurant);
}
#Override
public void onCancelled(DatabaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});
In my java class implementations; I am mapping the child nodes to hasmap like;
public HashMap<String,Menu> menus;
The Restaurant class
public class Restaurant {
private String name;
private String description;
public HashMap<String,Menu> menus;
public Restaurant() {}
public Restaurant(String name, String descriptioArrayList<Menu> menus)
{
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public HashMap<String, Menu> getMenus() {
return menus;
}
public void setMenus(HashMap<String, Menu> menus) {
this.menus = menus;
}
}
Everything works fine, I am successfully getting the restaurant root and mapping it to class. But, the menu and menuitems order are not in the same order as they are inserted from Firebase.
I have checked the datasnapshot, they are coming from Firebase unordered. I know the orderbykey() or getChildren() gets the data with the inserted order, but I am trying to do for the order both children menus and menuitems.
To sum up, I want to get whole restaurant root, its menus and menuitems the order that I inserted them. I want to do this only by getting restaurant root. Is there any way to do that? Thank you.
EDIT: Added the Restaurant.class and JSON version of the data uploaded.
Try this:
mDatabase.child("restaurants").child("restaurant_key").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ArrayList<Menu> menuArrayList = new ArrayList<>();
for(DataSnapshot menu : dataSnapshot.child("menus").getChildren()) {
ArrayList<String> menuItemArrayList = new ArrayList<>();
for(DataSnapshot menuItem : menu.child("menuItems").getChildren()) {
menuItemArrayList.add(menuItem.child("name").getValue().toString());
}
menuArrayList.add(new Menu(menu.child("name").getValue().toString(), menuItemArrayList));
}
currentRes = new Restaurant(dataSnapshot.child("name").getValue().toString(), dataSnapshot.child("description").getValue().toString(), menuArrayList);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) { }
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) { }
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) { }
#Override
public void onCancelled(DatabaseError databaseError) { }
});
If you do not understand what I'm doing please comment and I'll edit my answer.
Related
Hopefully someone can help me with this. Lets say I have a post and I want to track down the number of clicks it gets. How do I go about incrementing the value in the database (Firebase). For example the post has one click that count as 1 then it has another click that counts as 2 then so on and so fourth. I tried doing something but I'm getting this error. I really need your help on this. Thanks in advance
Error message
Can't convert object of type java.lang.Long to type com.myapp.poopy.Model_Information
My code
databaseReference = FirebaseDatabase.getInstance("https://poopy-43981.firebaseio.com/").getReference().child("Post").child(getid);
int count;
count = count ++;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
databaseReference.child("clicks").setValue(count+1);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
Json
{
"Post" : {
"lG71ennq86UIZ5a5Oqh8oaYAXe03" : {
"-MHNWmVK3rBnvnr0qcph" : {
"clicks" : 0,
"id" : "-MHNWmVK3rBnvnr0qcph",
}
}
},
Model_class
public Model_Information(String category, String headline, String mImageUrl,String created,String time,String id,String status ) {
this.mImageUrl = mImageUrl;
this.category = category;
this.headline = headline;
this.created=created;
this.time=time;
this.id=id;
this.status=status;
}
public Model_Information() {
}
public String getstatus() {
return status;
}
public void setstatus(String status) {
status = status;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public String getmImageUrl() {
return mImageUrl;
}
public void setmImageUrl(String mImageUrl) {
this.mImageUrl = mImageUrl;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getHeadline() {
return headline;
}
public void setHeadline(String headline) {
this.headline = headline;
}
//Class using model class
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String previousChildName) {
if (dataSnapshot.exists()) {
progressBar.setVisibility(View.GONE);
for (DataSnapshot postsnapshot : dataSnapshot.getChildren()) {
myUploads.clear();
Model_Information upload = postsnapshot.getValue(Model_Information.class);
myUploads.add(upload);
aAdapter = new Adapter(MainActivity2.this, myUploads);
recyclerView.setAdapter(aAdapter);
aAdapter.notifyDataSetChanged();
recyclerView.invalidate();
}
}
}
To be able to update the clicks value you need to know the complete path to that value. In your use-case there seem to be two variables in that path:
the UID
a push ID
Once you know both values, increment the value can be done with the (relatively new) ServerValue.increment operation like this:
DatabaseReference rootReference = FirebaseDatabase.getInstance("https://poopy-43981.firebaseio.com/");
DatabaseReference userReference = rootReference.child("Post").child(getid);
DatabaseReference countReference = userReference.child("-MHNWmVK3rBnvnr0qcph").child("clicks");
countReference.setValue(ServerValue.increment(1));
This is the structure of data from my firebase:
I have problem to retrieve all "menukedai" data. By using the code below, data from "menukedai" didnt come out. For your information, the data of "menukedai" will come from the user.
This is my attempt:
foodDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads").child("menukedai");
foodDatabaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
foodmenu foodmenu = postSnapshot.getValue(foodmenu.class);
fooddata.add(foodmenu);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(foodlist.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
This is my foodmenu class.
package com.example.trialfoodbuddy;
public class foodmenu {
private String Foodimage;
private String Foodname;
private CharSequence Foodprice;
public foodmenu(){
//empty constructor needed
}
public foodmenu(String foodimage, String foodname, CharSequence foodprice){
Foodimage = foodimage;
Foodname = foodname;
Foodprice = foodprice;
}
public String getFoodimage(){
return Foodimage;
}
public String getFoodname(){
return Foodname;
}
public CharSequence getFoodprice(){
return Foodprice;
}
public void setFoodimage(String foodimage){
Foodimage = foodimage;
}
public void setFoodname(String foodname){
Foodname = foodname;
}
public void setFoodprice(CharSequence foodprice){
Foodprice = foodprice;
}
}
I Believe you want to get the information nested under "menukedai" so you will need to add another loop for that information
foodDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads");
foodDatabaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot uploadSnapshot : dataSnapshot.getChildren()) {
// this is where you actually getting the information
for(DataSnapshot menuItemSnapshot : uploadSnapshot.child("menukedai").getChildren()){
foodmenu foodmenu = menuItemSnapshot.getValue(foodmenu.class);
fooddata.add(foodmenu);
}
}
}
// Log the values and check them to make sure you getting the data you want if always nice so I added it for you here
Log.i("Values","My values are:"+foodmenu);
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(foodlist.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Normally speaking, You should always use the variable names in your class in your Database so when you pulling the information, your constructor would know what value assign to which variable in your class.
I am making a to-do app, indeed my first firebase app. I have successfully implemented everything with a single text view(todo) under the firebase UID, by creating an array of the push id that returns the push ID when an element is clicked in the List view.
Here was my previous data structure:
Old data Structure
I am stuck with the problem that how can I get the push IDs of elements so that I can reach them and display them in my ListView.
This is the structure that I am trying to fetch :
New data structure
Here is the code that I use for adding and deleting data in the old
Structure
public void Upload(View v) {
String userId = myRootRef.push().getKey();
firebaseUniqueID =mAuth.getCurrentUser().getUid();
todoToUpload=todoEditText.getText().toString();
myRootRef.child(firebaseUniqueID).child(userId).setValue(todoToUpload);
startActivity(new Intent(AddTodo.this,showTodo.class));
Here's the code I use for adding and deleting:
FirebaseAuth mAuth;
FirebaseDatabase mDataBase= FirebaseDatabase.getInstance();
DatabaseReference myRootRef=mDataBase.getReference();
DatabaseReference userRef;
ListView listView;int pos;
private ArrayAdapter<String> adapter;
ArrayList<String> mTodo=new ArrayList<>();
ArrayList<String> keysList = new ArrayList<>();
adapter=new ArrayAdapter<String>(this,R.layout.custom_list_layout,R.id.tood,mTodo);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
pos=position;
AlertDialog.Builder mBuilder=new AlertDialog.Builder(showTodo.this);
View mView=getLayoutInflater().inflate(R.layout.custom_dialog_show,null);
Todo=mView.findViewById(R.id.todo);
Delete=mView.findViewById(R.id.delete);
Done=mView.findViewById(R.id.done);
closer=mView.findViewById(R.id.dialog_close);
mBuilder.setView(mView);
final AlertDialog dailog=mBuilder.create();
myRootRef.child(firebaseUniqueID).child(keysList.get(position)).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
todoOpened=dataSnapshot.getValue(String.class);
Todo.setText(todoOpened);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Done.isChecked())
{
mTodo.remove(pos);
adapter.notifyDataSetChanged();
//new code below
myRootRef.getRoot().child(firebaseUniqueID).child(keysList.get(pos)).removeValue();
keysList.remove(pos);
dailog.dismiss();
}
}
});
myRootRef.child(firebaseUniqueID)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot firebaseUniqueID : dataSnapshot.getChildren()) {
keysList.add(firebaseUniqueID.getKey());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
/*handle errors*/
}
});
userRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value= dataSnapshot.getValue(String.class);
mTodo.add(value);
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here's the JSON file for the old and new structures
{
"Z2H2ZkX56fYv3WKxE3a3nCaa8Q63" : {
"-LNPyZIkX8-uDDGeX-pN" : {
"Time" : "22:56",
"Todo" : "play"
},
"-LNPze7ppG1L0qFukZO-" : {
"Priority" : "High",
"Time" : "22:56",
"TimeSet" : "09:56",
"Todo" : "play till the sun goes down"
},
"-LNPzhBDDtHv_XSIERX_" : {
"Priority" : "High",
"Time" : "22:56",
"TimeSet" : "09:56",
"Todo" : "play till the sun goes ddawdawdawdwown"
}
}
}
{
"Z2H2ZkX56fYv3WKxE3a3nCaa8Q63" : {
"-LNQRCZSsYVPqn0tWghZ" : "play in the evening",
"-LNQRrLliVSxWBHcEIrv" : "I want to shine like a sun"
}
}
You get the key of a DataSnapshot by calling its getKey() method. So for example:
public void onDataChange(DataSnapshot dataSnapshot) {
todoOpened=dataSnapshot.getValue(String.class);
String key = dataSnapshot.getKey();
Todo.setText(key + ": "+ todoOpened);
}
you can display list as per your new structure dsplayed in :https://i.stack.imgur.com/E4DXI.png
FirebaseRecyclerOptions<Messages> options =
new FirebaseRecyclerOptions.Builder<"Your Class Name">()
.setQuery(mMessageThread.child("messages").limitToLast(500), "Your Class Name".class)
.setLifecycleOwner(this)
.build();
use this with firebase adapter.
Then get ToDo text and display it.
I'm trying to get the value of my firebase tree
I got a class get_categories
public class get_categories {
private String Name;
public get_categories(){
}
public String getName(){
return Name;
}
}
Then I declared the firebase
mRef = new Firebase("https://...../Users/Categories");
And try to retrieve my data with OnChildEventListener
mRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.e("Count " ,""+dataSnapshot.getChildrenCount());
//Log.e("VALUES " ,""+dataSnapshot.child("Details").getValue());
get_categories getCatName = dataSnapshot.child("Details").getValue(get_categories.class);
Log.e("NAME " ,""+getCatName.getName());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
But I got an error
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Name" (class com.app.pierre.myapp.get_categories), not marked as ignorable (0 known properties: ]) at [Source: java.io.StringReader#9d0f705; line: 1, column: 10] (through reference chain: com.app.pierre.myapp.get_categories["Name"])
What am I doing wrong ?
I used this case as reference:
https://www.firebase.com/docs/android/guide/retrieving-data.html
Well first change your Model like this,
public class GetCategories {
private String Name;
public GetCategories(){
}
public GetCategories(String name){
this.Name = name;
}
public String getName(){
return Name;
}
}
and Push data using Model class Constructor..
GetCategories model = new GetCategories("yourValues");
mReference.child("Details").push().setValue(model);
and Now you can get it like this way..
mRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
GetCategories newPost = eventSnapshot.getValue(GetCategories.class);
Log.e("NAME " ,""+ newPost.getName());
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
The name of the property on your JSON starts with an uppercase letter. But by the rules of JavaBean properties, getName() correspond to a property called name (with a lowercase n). So the two don't match up.
One way to get this working is to not use a setter, but instead use a public field:
public class get_categories {
public String Name;
}
With this you're bypassing the JavaBean logic and get a direct mapping.
I'm new at using maps, how can we get object of custom Class from Map..
i.e.
feedSendModelClass:
public class feedSendModelClass {
private String content;
private String picThumbnail;
private String picurl;
private String videourl;
private String videoThumbnail;
private String mTime;
public feedSendModelClass() {
//blank for firebase
}
public String getTime() {
return mTime;
}
public void setTime(String time) {
mTime = time;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getVideoThumbnail() {
return videoThumbnail;
}
public void setVideoThumbnail(String videoThumbnail) {
this.videoThumbnail = videoThumbnail;
}
public String getVideourl() {
return videourl;
}
public void setVideourl(String videourl) {
this.videourl = videourl;
}
public String getPicurl() {
return picurl;
}
public void setPicurl(String picurl) {
this.picurl = picurl;
}
public String getPicThumbnail() {
return picThumbnail;
}
public void setPicThumbnail(String picThumbnail) {
this.picThumbnail = picThumbnail;
}
}
Map
Map<String, feedSendModelClass> feedKeys = (Map<String,feedSendModelClass>) dataSnapshot.getValue();
Datasnapshot:
DataSnapshot { key = feedsMetaPool, value = {20160708155218759={content=bzzzhss, picurl=https://firebasestorage.googleapis.com/v0/b/rootssahaj.appspot.com/o/feedsImages%2FnonThumbs%2F201607081552353353553518759sahaj9917730102?alt=media&token=ce1c6e7c-28c5-442e-9405-4468bf5fc204, time=08 Jul, picThumbnail=https://firebasestorage.googleapis.com/v0/b/rootssahaj.appspot.com/o/feedsImages%2Fthumbs%2F20353353535355353160708155218759sahaj9917730102?alt=media&token=14d33963-f3da-4407-a08f-ab0afce21ace}, 20160708164100152={content=sj sjs skss sksssvsjm, picurl=https://firebasestorage.googleapis.com/v0/b/rootssahaj.appspot.com/o/feedsImages%2FnonThumbs%2F201607081641003535152sahaj9917730102?alt=media&token=323c4a27-1850-4bc9-adea-34e5319ac506, time=08 Jul, picThumbnail=https://firebasestorage.googleapis.com/v0/b/rootssahaj.appspot.com/o/feedsImages%2Fthumbs%2F20160708164100152sahaj9917730102?alt=media&token=0b064b46-2f14-49af-b3e6-7a573f6c2d3f}, 20160708142314069={content=dadax, picurl=https://firebasestorage.googleapis.com/v0/b/rootssahaj.appspot.com/o/feedsImages%2FnonThumbs%2F2016070rdgdg54353535358142314069sahaj9917730102?alt=media&token=19d03f11-d12f-43c1-96f5-ca397a9179c9, time=08 Jul, picThumbnail=https://firebasestorage.googleapis.com/v0/b/rootssahaj.appspot.com/o/feedsImages%2Fthumbs%2F20160735353508142314069sahaj9917730102?alt=media&token=ab9c73eb-ec44-46ae-9daa-6fc508cb08a6} }
This has become tricky for me..Thanks..
There could be some other way round to do it through firebase
If you are asking how you retrieve the feedSendModelClass object from the map named feedKeys, then this syntax should work:
feedKeys.get(key)
The key is your String, and the object is the feedSendModelClass object. However, first you'd need to put key and value pairs into the map (so it's not empty), with feedKeys.put(key, value), where the key is a String and value is the feedSendModelClass.
If this totally doesn't answer your question, I apologize, but from your description, it is a bit difficult to understand what you need help with.
On an unrelated note, it would be more appropriate to name your class FeedSendModelClass, as per Java conventions classes start with a capital letter.
If you're using Firebase then you can use a ChildEventListener. It calls the onChildAdded() method once for every initial child in the node and everytime a new child is added. Then you can add the Object to an ArrayList directly (or do whatever you want with it)
ArrayList<feedSendModelClass> feedKeysArrayList = new ArrayList<>();
DatabaseReference feedKeysRef = FirebaseDatabase.getInstance().getReference("path/to/the/feedkeys");
feedKeysRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
feedKeysArrayList.add(dataSnapshot.getValue(feedSendModelClass.class));
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
// Add appropriate code
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
// Add appropriate code
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
// Add appropriate code
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Add appropriate code
}
});