How to retrieve nested data from firebase - android

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.

Related

Not able to retrieve data from Firebase real time database in Android studio

I'm new to the firebase and android studio. I'm working on a project in which I have to fetch details of the current user and display the name. It is throwing "user doesn't exist' toast even if I'm logged in I'm attaching everything below. Maybe I have done some mistakes please let me know.
Code to fetch details of the current user
public class Succesfully_sign_up extends AppCompatActivity {
DatabaseReference reff;
TextView name;
Button signout;
FirebaseUser curr_user;
String curr_user_str;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_succesfully_sign_up);
name = findViewById(R.id.name);
curr_user=FirebaseAuth.getInstance().getCurrentUser();
if(curr_user!=null)
{
curr_user_str = curr_user.getUid();
reff = FirebaseDatabase.getInstance().getReference("userdetails");
reff.child(curr_user_str).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
HelperClass data = dataSnapshot.getValue(HelperClass.class);
if (data != null) {
name.setText(data.getFullname_hc());
} else {
Toast.makeText(Succesfully_sign_up.this, "User does't exist", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
else
{
startActivity(new Intent(Succesfully_sign_up.this,student_signup.class));
}
}
}
My HelperClass
public class HelperClass {
String fullname_hc,amizone_id_hc,mobile_num_hc,email_id_hc;
public HelperClass()
{
}
public HelperClass(String fullname_hc, String amizone_id_hc, String mobile_num_hc, String email_id_hc) {
this.fullname_hc = fullname_hc;
this.amizone_id_hc = amizone_id_hc;
this.mobile_num_hc = mobile_num_hc;
this.email_id_hc = email_id_hc;
}
public String getFullname_hc() {
return fullname_hc;
}
public void setFullname_hc(String fullname_hc) {
this.fullname_hc = fullname_hc;
}
public String getAmizone_id_hc() {
return amizone_id_hc;
}
public void setAmizone_id_hc(String amizone_id_hc) {
this.amizone_id_hc = amizone_id_hc;
}
public String getMobile_num_hc() {
return mobile_num_hc;
}
public void setMobile_num_hc(String mobile_num_hc) {
this.mobile_num_hc = mobile_num_hc;
}
public String getEmail_id_hc() {
return email_id_hc;
}
public void setEmail_id_hc(String email_id_hc) {
this.email_id_hc = email_id_hc;
}
}
I think you have created the database manually, your user id 8448.... is not generated by the Firebase android, so it is showing that error. If not then please share the code of creation of that above database structure.
How about looping through the children and accessing data:
//the reference
reff = FirebaseDatabase.getInstance().getReference("userdetails");
//the reading
reff.child.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//loop through every possible child under "userdetails"
for(DataSnapshot ds : dataSnapshot.getChildren()){
String fullName = ds.child("fullname_hc").getValue(String.class);
name.setText(fullName);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Why my constructor in RecyclerView is getting called late?

I am creating a recyclerView for my project for which I am using 2 functions in onCreate,
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cart);
System.out.println("dsdsds");
pref = getSharedPreferences("pref", Context.MODE_PRIVATE);
dbReff = FirebaseDatabase.getInstance().getReference().child("CartItem");
dbToken = FirebaseDatabase.getInstance().getReference().child("TokenNumber");
CreateList();
BuildRecyclerView();
}
Here I am creating a list which is set in adapter in the first function,
cartItemArrayList = new ArrayList<>();
dbReff.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
if(!data.child("name").getValue().toString().equals("notToDisplayThisItem")) {
cartItemArrayList.add(new CartItemIdQuant(
data.child("id").getValue().toString(),
data.child("quant").getValue().toString(),
data.child("name").getValue().toString(),
data.child("price").getValue().toString()
));
Log.e("THE DATA", data.toString());
}
}
Log.e("INHERE","");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
and the 2nd function is as followed,
recyclerView = findViewById(R.id.recyclerCartView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
cartAdapter = new CartAdapter(cartItemArrayList);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(cartAdapter);
log.e("Message"," from build recyclerVIew");
and my class for the data item is as followed,
public class CartItemIdQuant {
private String ID;
private String Quant;
private String Name;
private String Price;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getPrice() {
return Price;
}
public void setPrice(String price) {
Price = price;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public String getQuant() {
return Quant;
}
public void setQuant(String quant) {
Quant = quant;
}
public CartItemIdQuant(String NewID, String NewQuant,String NewName,String NewPrice){
ID = NewID;
Quant = NewQuant;
Name = NewName;
Price = NewPrice;
Log.e("the" , "Method Called From Constructor");
}
public CartItemIdQuant(){
}
}
here the log of Data that I receive and print in the 1st function is printed and the log I print in the constructor is then printed after 2 seconds. I want to know the reason for the delay in the call, as I have to put a delay for it to work properly which I do not want.
Please help me, thank you in advance.
EDIT:
here as per the comment, is the logcat in which the message from the 2nd function is called before the list could be created.
2020-02-21 15:20:03.434 547-547/com.chinuEvent.chinuevent E/Message: from build recyclerVIew
2020-02-21 15:20:03.837 547-547/com.chinuEvent.chinuevent E/the: Method Called From Constructor
2020-02-21 15:20:03.838 547-547/com.chinuEvent.chinuevent E/THE DATA: DataSnapshot { key = 02, value = {price=15, name=Orange, id=02, quant=3} }
It is actually completely normal to set the adapter to the view before the data is loaded. In many cases (some of) the data is loaded (or modified) asynchronously, and you'll often want to show those updates as they come in.
All you need to do for that is notify the adapter that its underlying data has changed. The adapter will then notify the view(s), and those will repaint with the updated data.
To notify the adapter, call its notifyDataSetChanged() in your onDataChange handler after you've modified cartItemArrayList:
dbReff.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
if(!data.child("name").getValue().toString().equals("notToDisplayThisItem")) {
cartItemArrayList.add(new CartItemIdQuant(
data.child("id").getValue().toString(),
data.child("quant").getValue().toString(),
data.child("name").getValue().toString(),
data.child("price").getValue().toString()
));
}
}
cartAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore possible errors
}
});

A new text should be displayed in textview every time the app launches

I have a textview in MainActivity.java. There are 5 strings (sentences) which are stored in firebase database. What I want is every time the MainActivity.java launches, a new string should be fetched from the database and must be displayed in the textview. But it only fetches the first string. I am not sure how to make this work! Is there any workaround? Any Help is appreciated.
MainActivity.java
public class Gridshow extends AppCompatActivity{
TextView myText;
private DatabaseReference database;
#Override
protected void onCreate(Bundle SavedInstanceState) {
super.onCreate(SavedInstanceState);
myText = (TextView) findViewById(R.id.Attri);
database = FirebaseDatabase.getInstance().getReference("StringList");
database.child("String1").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Sample son file:
{
"StringList" : {
"String1" : "Valley Rovers",
"String2" : "John Murphy",
"String3" : "Hello all",
"String4" : "See you all",
"String5" : "Hey all"
}
}
The problem is that you're directly saying to FB to retrieve just the first string in here:
database.child("String1").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You should retrieve the whole list and randomly choose the new string:
ArrayList<String> stringList = new ArrayList<>();
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, String> entries = (Map<String, String>) dataSnapshot.getValue();
stringList.addAll(entries.values());
selectString(stringList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
public void selectString(ArrayList<String> list){
Random ran = new Random();
int x = ran.nextInt(list.size());
myText.setText(list.get(x));
}
use this
database = FirebaseDatabase.getInstance().getReference().child("StringList");
database.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Well, in this line:
database.child("String1").addValueEventListener
You are fetching just String1. You should instead use something like this:
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(int i = 0;i<dataSnapshot.getChildren().size();i++){
if(i==positionOfStringYouWant){
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Show list of data on my firebase database

Hello I'm trying to show the data's that i have inputted in my activity, but the problem is i don't have any idea how to, I'm at lost on the data snapshot one. I'm trying to like only show the name and email
My database
my code and progress so far
public class AdminActivity extends AppCompatActivity {
private DrawerLayout mdrawerl;
private ActionBarDrawerToggle mtoggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Accounts").child("Users");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
collectName((Map<String,Object>)dataSnapshot.getValue());
}
private void collectName(Map<String, Object> value) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
reference that i used How to get all child's data in firebase database?
1- Create a model class that will hold the objects of user. In your case it would be
public class User {
private String email;
private String name;
private int type;
public User() {
}
public User(String email, String name, int type) {
this.email= email;
this.name= name;
this.type= type;
}
}
2 - Create a ArrayList that will hold items of User
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<User> userList = new ArrayList();
for (DataSnapshot child :
dataSnapshot.getChildren()) {
User user = child.getValue(User.class);
userList.add(user )
}
//Here you have all user you can pass ```userList``` to your method furthur
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope this will help you.

Firebase - retrieve data in Android

I have a data looks like this:
{
"courses" : {
"Business" : {
"-KOBuojCGl_KVNgCx6l3" : {
"courseCode" : "BUS2202",
"courseName" : "Business Mathematics"
},
"-KOCH9RvYkwIamb0oxi8" : {
"courseCode" : "BUS2302",
"courseName" : "Business Fundamentals"
}
},
"Computing & IT" : {
"-KOBukFDN8eDjzF77haS" : {
"courseCode" : "SDT2201",
"courseName" : "System Designs"
},
"-KOBuriS_C5njfhAkV_P" : {
"courseCode" : "SDT3201",
"courseName" : "Computer Project"
},
"-KOD-E81rtXhzEmSeRPx" : {
"courseCode" : "SDT2202",
"courseName" : "System Designs Year 2"
},
}
}
}
And an UI looks like this:
When user selects Business Fundamentals, textview1 should display BUS2302 and textview2 should display Business Fundamentals.
Codes I'm trying now:
public class MainActivity extends AppCompatActivity{
private TextView tv1, tv2;
private DatabaseReference mRef;
private String code, name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRef = FirebaseDatabase.getInstance().getReference().child("courses").child("Business");
tv1 = (EditText) findViewById(R.id.textview1);
tv2 = (EditText) findViewById(R.id.textview2);
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
CourseDetails courseDetails = dataSnapshot.getValue(CourseDetails.class);
code = courseDetails.getCourseCode();
name = courseDetails.getCourseName();
tv1.setText(code);
tv2.setText(name);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
CourseDetails class:
public class CourseDetails {
private String courseCode;
private String courseName;
public CourseDetails() {
}
public CourseDetails(String courseCode, String courseName) {
this.courseCode = courseCode;
this.courseName = courseName;
}
public String getCourseCode() {
return courseCode;
}
public void setCourseCode(String courseCode) {
this.courseCode = courseCode;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
}
When I run the codes, both the textviews just blank, and no error message. When I changed mRef ValueEventListener to this:
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
tv1.setText(dataSnapshot.getValue().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The whole JSON data printed out in textview1, so I know my data is there. But when I use getCourseCode() and getCourseName(), the textviews are blank. Any suggestions?
I have another question which the codes will be used to get the push key of a course, then only display the course code and name accordingly. The question can be found here
In your MainActivity for mRef it reference till node Business of the database which has further two children with keys which I think are generated using push. So, I think you have to iterate over it's children. Can you try something like below:
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// for each children
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
CourseDetails courseDetails = snapshot.getValue(CourseDetails.class);
code = courseDetails.getCourseCode();
name = courseDetails.getCourseName();
tv1.setText(code);
tv2.setText(name);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
If this gives some result apart from null, then may have to work in mapping textViews with respective to key.

Categories

Resources