the maxid integer variable should have the value for the getChildrenCount() from the firebase database, but it seems that the addValueEventListener is not working.
The following is my java code from Android Studio:
#IgnoreExtraProperties
public class ProfileID_Generator extends AppCompatActivity {
public int maxid;
private int ProfileID;
private String value;
private final DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("User");
public ProfileID_Generator(){}
public int profileID_generate(){
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
maxid = (int) snapshot.getChildrenCount();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
ref.child(Integer.toString(maxid)).child("ProfileID").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
String val = snapshot.getValue(String.class);
value = val;
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
if(maxid==0){
ProfileID = 10001;
}
else{
ProfileID = Integer.parseInt(value)+1;
}
return ProfileID;
}
}
The following is the data from the realtime database from firebase:
All data is loaded from Firebase (and most cloud APIs) asynchronously, which changes the order in which code executes from what you may expect and be used to.
The problem is not that getChildrenCount isn't working, but that ref.child(Integer.toString(maxid)) is executed before maxid = (int) snapshot.getChildrenCount();. It's easiest to see this if you add some logging:
Log.i("Firebase", "Start loading maxid")
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
Log.i("Firebase", "Got data for maxid")
maxid = (int) snapshot.getChildrenCount();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
Log.i("Firebase", "Start loading ProfileID")
ref.child(Integer.toString(maxid)).child("ProfileID").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
String val = snapshot.getValue(String.class);
value = val;
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
When you run this code it logs:
Start loading maxId
Start loading ProfileID
Got data for maxid
This may not be the order in which you expected the output, but it is working as designed and explains perfectly why your code doesn't work: by the time you starting loading the ProfileID, the maxid isn't known yet.
The solution for this type of problem is always the same: any code that needs the data from the database has to be inside onDataChange, be called from there, or otherwise synchronized.
So the simplest fix is to move the code that loads the ProfileID into the onDataChange that sets maxid:
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
maxid = (int) snapshot.getChildrenCount();
ref.child(Integer.toString(maxid)).child("ProfileID").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
String val = snapshot.getValue(String.class);
value = val;
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
This is an incredibly common problem and stumbling block for developers that are new to asynchronous APIs, so I recommend reading up on some more questions about it, such as:
getContactsFromFirebase() method return an empty list
Setting Singleton property value in Firebase Listener
Related
Here is my Firebase Realtime Database structure:
I want to retrieve each and every image in a child(images1,images2,images3,images4 are the child names)
private void loadmybanners1() {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("BannerImages");
ref.orderByChild("images2").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
final String myImg1 = "" + ds.child("image").getValue();
try{
Picasso.get().load(myImg1).networkPolicy(NetworkPolicy.OFFLINE).into(ban2Iv, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
Picasso.get().load(myImg1).into(ban2Iv);
}
});
} catch (Exception e) {
ban2Iv.setImageResource(R.drawable.ic_image);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
I have used this code to retrieve the image2. But from that, I can only retrieve the images1 child data. What are the modifications to do?
I want to retrieve each and every image in a child
To get each and every child within your BannerImages node, there is no need to use a query, you can simply use a DatabaseReference, as in the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference bannerImagesRef = rootRef.child("BannerImages");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String myImg1 = dataSnapshot.child("images1").child("image").getValue(String.class);
Picasso.get().load(myImg1)
String myImg2 = dataSnapshot.child("images2").child("image").getValue(String.class);
Picasso.get().load(myImg2)
//And so on for the other images3, images4, and images5 children
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore errors!
}
};
bannerImagesRef.addListenerForSingleValueEvent(valueEventListener);
Add this dependency
implementation 'com.github.bumptech.glide:glide:4.10.0'
After getting Url from Firebase.Just Use below line
Glide.with(context).load(Firbase Url).into(imageView);
ccontacts = new ArrayList<>();
DatabaseReference dbGelenler = db.getReference("Filmler");
dbGelenler.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot gelenler:dataSnapshot.getChildren()){
ccontacts.add(new Data(gelenler.getValue(Film.class).getAciklama(),gelenler.getValue(Film.class).getBen(),gelenler.getValue(Film.class).getImdb(),gelenler.getValue(Film.class).getIsim(),gelenler.getValue(Film.class).getIzlemeLinki(),gelenler.getValue(Film.class).getKategori(),gelenler.getValue(Film.class).getNe(),gelenler.getValue(Film.class).getService(),gelenler.getValue(Film.class).getTrailer(),gelenler.getValue(Film.class).getUrl(),gelenler.getValue(Film.class).getWhat(),gelenler.getValue(Film.class).getYear()));
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
for (Data d:ccontacts){
b.setText(d.getIsim());
}
When I directly set the text via gelenler.getValue() it works, however when I want to populate an ArrayList with this information it fails and receives null. Any help would be appreciated.
I need to get data from a table and use it as a reference in order to get another data in another table.
Here is my table structure
Here is how I get the data in java class.IN my table, I have stored an attribute called 'theraid' which I need to retrieve it and use it as a reference in order to get another attribute named 'name' in another table.
a=new ArrayList<AppointmentObject>();
namelist=new ArrayList<String>();
databaseReference= FirebaseDatabase.getInstance().getReference().child("appointment");
databaseReference.orderByChild("userid").equalTo(userid1).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshot1: dataSnapshot.getChildren()) {
AppointmentObject thera= dataSnapshot1.getValue(AppointmentObject.class);
a.add(thera);
final String theraid = dataSnapshot1.child("theraid").getValue().toString();
refThera = FirebaseDatabase.getInstance().getReference().child("alluser").child("thera");
refThera.child(theraid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot3) {
for (DataSnapshot ds: dataSnapshot3.getChildren())
{
***************error this line below********************************
String text = ds.child("name").getValue().toString();
namelist.add(text);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), "Oh no!", Toast.LENGTH_SHORT).show();
throw databaseError.toException();
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), "Oh no!", Toast.LENGTH_SHORT).show();
}
});
adapter=new MyRecyclerviewPAppointment(MainActivityPAppointment.this, a,namelist);
rv.setAdapter(adapter);
Here is the recyclerview class in order to display the data that retrieve via the java class.
public class MyRecyclerviewPAppointment extends RecyclerView.Adapter<MyRecyclerviewPAppointment.MyViewHolder> {
private Context context;
ArrayList<AppointmentObject> alist;
ArrayList<String> namelist1;
public MyRecyclerviewPAppointment(Context c, ArrayList<AppointmentObject> t,ArrayList<String> namelist) {
context = c;
alist = t;
namelist1=namelist;
}
#Override
public void onBindViewHolder(#NonNull final MyRecyclerviewPAppointment.MyViewHolder holder,final int position) {
holder.tdate.setText(alist.get(position).getDate());
holder.ttime.setText(alist.get(position).getTiming());
holder.tname.setText(namelist1.get(position));
// holder.tstatus.setText(alist.get(position).getTiming());
}
#Override
public int getItemCount() {
return alist.size();
}
}
I don't know what's wrong to my code but it can't work, it just keeps stopped.
Here is the error. May I know where is the mistake in my d=code? Thanks for helping me :).
In the second listener, your databaseReference is at node theraid. Therefore you don't have to loop to be able to access the value of name. So change the following code:
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot3) {
for (DataSnapshot ds: dataSnapshot3.getChildren()) {
String text = ds.child("name").getValue().toString();
namelist.add(text);
}
}
Into this:
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot3) {
String text = dataSnapshot3.child("name").getValue().toString();
namelist.add(text);
}
Firebase just silently don't get the data.
I work on it a lot of time but still don't really understand what is a problem.
Probably it's very simple mistake so get my excuses please
fRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
ids = dataSnapshot.child("dictionary").child("fruitIds").getValue(DictionaryIDs.class);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
DictionaryIds.class code
package com.example.asuper.mluvitslova;
import com.google.firebase.database.FirebaseDatabase;
import java.util.ArrayList;
public class DictionaryIDs {
private ArrayList<String> fruitIds = new ArrayList<>();
public DictionaryIDs() {
}
public DictionaryIDs(ArrayList<String> fruitIds) {
this.fruitIds = fruitIds;
}
public void addFruitId(String id){
fruitIds.add(id);
}
public ArrayList<String> getFruitIds(){
return fruitIds;
}
public void setFruitIds(ArrayList<String> fruitIds){
this.fruitIds = fruitIds;
}
}
And in log just NOTHING
This code must just get me the DictionaryIds.class file but in fact Firebase just get me null object.
Firebase database structure
Under the last fruitIds child, there are no DictionaryIDs objects, there are simple strings. To get all those ids, you need to loop through the DataSnapshot object using getChildren() method like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference fruitRef = rootRef.child("dictionary").child("fruitIds").child("fruitIds");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String id = ds.getValue(String.class);
Log.d(TAG, id);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
fruitRef.addListenerForSingleValueEvent(valueEventListener);
The result in your logcat will be all those ids.
I want to retrieve only the date and all the date element at once and store them in array in the firebase as shown below.
i have used the following code to retrieve but failed to that.
public void showData(View view) {
final ArrayList<String> date = new ArrayList<>();
firebaseDatabase = FirebaseDatabase.getInstance().getReference().child("Date");
firebaseDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
date.add(dataSnapshot.getValue().toString());
display.setText(dataSnapshot.getValue().toString());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Please help to find a solution for this.
The firebase reference is wrong, you should go from the top node to the date node.
Change this:
firebaseDatabase = FirebaseDatabase.getInstance().getReference().child("Date");
into this:
firebaseDatabase = FirebaseDatabase.getInstance().getReference().child("Name");
firebaseDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
date.add(datas.child("Date").getValue().toString());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Since you want to get all Date then put the firebase reference at the node Name and loop inside the names to be able to retrieve all the dates.
If you want to get the date of one user example Ravi, then you do not need to loop, you can do the following:
firebaseDatabase = FirebaseDatabase.getInstance().getReference().child("Name").child("Ravi").child("Date");
firebaseDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
date.add(dataSnapshot.getValue().toString());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
As said by #PeterHaddad in the previous answer, the sequence to access the data you have taken is not right. You may try this way, if nothing else helped until yet.
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
rootRef.child("Names").orderByChild("Date").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot ds: dataSnapshot.getChildren()){
date.add(ds.getValue(String.class));
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
//Also as you've told that code is not working, please tell, what exactly is not working