Fetch single value from Firebase against id - android

I am having problem while fetching a value "rate_perltr" against user id I couldn't fetch so far, I have tried all way but still getting error.
myDatabaseRateFetch = FirebaseDatabase.getInstance().getReference("Customers");
customerName.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
myDatabaseRateFetch.orderByChild("cust_id").equalTo(7040).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
try
{
String ratePerLtr = dataSnapshot.getValue(String.class);
Rate rate = dataSnapshot.getValue(Rate.class);
rate_fetch = rate.getRate_perltr();
}catch (Exception e)
{
Toast.makeText(MainActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(MainActivity.this, ""+databaseError.toString()+"", Toast.LENGTH_SHORT).show();
}
});
rate.setText(Html.fromHtml(" "+ String.valueOf(rate_fetch) +""));
return false;
}
});
}
Rate Model Class
package com.example.wms;
public class Rate {
private double rate_perltr;
public Rate()
{
}
public Rate(double rate_perltr) {
this.rate_perltr = rate_perltr;
}
public double getRate_perltr() {
return rate_perltr;
}
public void setRate_perltr(double rate_perltr) {
this.rate_perltr = rate_perltr;
}

Seems like there is an issue with your Rate Model. It is unable to map your firebase data to your Rate model.

try this one
private void onDataChange(DataSnapshot datasnapshot){
for(DataSnapshot snapshot : datasnapshot.getChildren){
Rate rateFetch = snapshot.getValue(Rate.class);
rateF[0] = ratefetch.getRate_perltr();
}
}

Try this. If you just want to fetch the result of a field from your firebase table, you can do this in your onDataChange() method
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Rate r = new Rate(); //
try {
r.setVar((String) dataSnapshot.child("var").getValue()); //var is the firebase field
} catch (Exception e) {
r.setVar("whatever you want here");
}
}
If you want to fill a model with the firebase result, ensure that instance variables names matches the fields in the firebase table then you can do this:
public void onDataChange(#NonNull DataSnapshot datasnapshot){
for(DataSnapshot snapshot : datasnapshot.getChildren){
Rate rate = snapshot.getValue(Rate.class);
//then get any variable you want from rate
}
}

Related

How do I wait until my data is retrieved from Firebase? [duplicate]

This question already has answers here:
How to return DataSnapshot value as a result of a method?
(6 answers)
Closed 3 years ago.
My problem is that I need to wait for the data from Firebase to be retrieved on the method "onDataChange" before ending my main method.
My code is (CalendarDbHelper) :
public synchronized ArrayList<Day> listDays()
{
final CountDownLatch done = new CountDownLatch(1);
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
{
for(DataSnapshot postSnapShot:dataSnapshot.getChildren())
{
Day day=postSnapShot.getValue(Day.class);
listDays.add(day);
}
}
done.countDown();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
try {
done.await();
} catch(InterruptedException e) {
e.printStackTrace();
}
return listDays;
}
As you can see, I'm already trying to wait with a CountDownLatch, but it doesn't work : it gets stuck.
I need the listDays for the activity "CalendarActivity" where I use it like this :
//Real initialization of the database
db = FirebaseDatabase.getInstance().getReference();
mDatabase = new CalendarDbHelper(db);
final List<Day> allDays = mDatabase.listDays();
//Activating things to click on
if(allDays.size() > 0){
calendarRV.setVisibility(View.VISIBLE);
calendarRVAdapter = new CalendarAdapter(this, allDays, new CalendarAdapter.OnListItemClickListener() {
#Override
public void onListItemClick(int clickedItemIndex) {
String id = allDays.get(clickedItemIndex).getId();
MyCustomAlertDialog(id);
}
});
calendarRV.setAdapter(calendarRVAdapter);
}else {
calendarRV.setVisibility(View.GONE);
Toast.makeText(this, "There is no product in the database. Start adding now", Toast.LENGTH_LONG).show();
}
if this is your "main method",you should put the return data when the onDataChange is triggered
Try this.
public synchronized ArrayList<Day> listDays()
{
final CountDownLatch done = new CountDownLatch(1);
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
if(dataSnapshot.exists())
{
for(DataSnapshot postSnapShot:dataSnapshot.getChildren())
{
Day day=postSnapShot.getValue(Day.class);
listDays.add(day);
}
// Do whatever you want to do with your list from here..
}
done.countDown();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
try {
done.await();
} catch(InterruptedException e) {
e.printStackTrace();
}
return listDays;
}

Can't convert object of type java.lang.String to type

I have a problem after I add another table to my firebase database. it gives me following error:
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type ...
here is my code, which works fine if I have database like this:
and code:
Main activity code:
rvOrder = (RecyclerView) findViewById(R.id.rvOrders);
rvOrder.setLayoutManager(new LinearLayoutManager(this));
databaseReference= FirebaseDatabase.getInstance().getReference();
firebaseHelper=new FirebaseHelper(databaseReference);
myAdapter=new MyAdapter(this,firebaseHelper.retrieve());
rvOrder.setAdapter(myAdapter);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
rvOrder.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Firebase helper code:
public class FirebaseHelper {
DatabaseReference databaseReference ;
Boolean saved = null;
ArrayList<Order> orders = new ArrayList<>();
public FirebaseHelper(DatabaseReference databaseReference) {
this.databaseReference = databaseReference;
}
public Boolean save(Order order) {
if (order == null) {
saved = false;
} else {
try {
databaseReference.child("Orders").push().setValue(order);
saved = true;
} catch (DatabaseException e) {
e.printStackTrace();
saved = false;
}
}
return saved;
}
private void fetchData(DataSnapshot dataSnapshot) {
orders.clear();
for(DataSnapshot ds : dataSnapshot.getChildren()) {
System.out.println(ds.getValue(Order.class));
Order order = ds.getValue(Order.class);
orders.add(order);
}
}
public ArrayList<Order> retrieve() {
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return orders;
}
If I change my code to this (which I saw in this question link to the question ):
in Main activity:
databaseReference= FirebaseDatabase.getInstance().getReference();
to
databaseReference= FirebaseDatabase.getInstance().getReference().child("Orders");
and in firebasehelper:
for(DataSnapshot ds : dataSnapshot.getChildren()) {
System.out.println(ds.getValue(Order.class));
Order order = ds.getValue(Order.class);
orders.add(order);
}
to
System.out.println(dataSnapshot.getValue(Order.class));
Order order = dataSnapshot.getValue(Order.class);
orders.add(order);
then I am able to add another tables to database but I just get only the last item from the Orders table.
I want to add many tables with multiple items into the database and also I want to get all items from the "Orders" table.
Can anybody suggest me anything?
In your first code snippet you read from the root of the database. Since you're trying to read orders, you should read from /Orders instead:
databaseReference= FirebaseDatabase.getInstance().getReference();
firebaseHelper=new FirebaseHelper(databaseReference);
//myAdapter=new MyAdapter(this,firebaseHelper.retrieve());
//rvOrder.setAdapter(myAdapter);
databaseReference.child("Orders").addValueEventListener(new ValueEventListener() {
Now in your onDataChange you can read the orders by looping over them. Since you already do precisely that in FirebaseHelper.fetchData, you can call that method:
public void onDataChange(DataSnapshot dataSnapshot) {
firebaseHelper.fetchData(dataSnapshot);
}
Now all that is left is to wire up the data from firebaseHelper.orders to an adapter and the view:
public void onDataChange(DataSnapshot dataSnapshot) {
firebaseHelper.fetchData(dataSnapshot);
myAdapter=new MyAdapter(this,firebaseHelper.orders);
rvOrder.setAdapter(myAdapter);
}
This last step will require that you make FirebaseHelper.orders public, and probably some of the variables must be final.
I think you need to update this method accordingly:
public Boolean save(Order order) {
if (order == null) {
saved = false;
} else {
try {
databaseReference.child("Orders").push().setValue(order);
saved = true;
} catch (DatabaseException e) {
e.printStackTrace();
saved = false;
}
}
return saved;
}
Try to change:
databaseReference.child("Orders").push().setValue(order);
To:
databaseReference.child("Orders").child(order.getId).setValue(order);
Also, to retreive all Orders keep using the enhanced loop:
for(DataSnapshot ds : dataSnapshot.getChildren()) {
System.out.println(ds.getValue(Order.class));
Order order = ds.getValue(Order.class);
orders.add(order);
}

Query firebase database and retrieve specific data

I have an android application that uses Firebase database.
What i want
I have input field as a username. When a user enters his username, I want to check whether this user exists or not. If yes, then allow him to login in.
[As u can see username:][2]
I want to get this username. I have tried some code, but it's not getting what I want.
here is code sample:
mUserRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren())
{
UserData userData = child.getValue(UserData.class);
if(c_user_name == null)
{
c_user_name= " ";
}
online_user_id=c_user_name+userData.getmUser_name();
c_user_name=online_user_id.toString();
Log.v("E_VALUE","User_new:"+c_user_name);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
what error i am getting is
Can't convert object of type java.lang.String to type packagename.UserData
and here is my UserData class
public class UserData {
String mUser_name,mUser_email;
public UserData() {
}
public UserData(String mUser_name, String mUser_email) {
this.mUser_name = mUser_name;
this.mUser_email = mUser_email;
}
public String getmUser_name() {
return mUser_name;
}
public String getmUser_email() {
return mUser_email;
}
}
This can be achieved by using orderByChild, and use addListenerForSingleValueEvent , since you want to read it only once.
Check below code:
mUserRef.orderByChild("User_Name").equalTo("usernameInputFieldText").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists)
{
/// username exsits
}
else
{
/// user name doesn't exists
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Firebase Datasnapshot values are not getting reflected in associated class object

I am newbie in Firebase. I am trying to fetch data from firebase to object of the related class. The datasnapshot gets the value from Firebase, but the same values are not getting assigned to the object.
Below is my Firebase Structure:
Here is what getting me the problem:
myRef =database.getReference();
myRef.child("Tables").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded( DataSnapshot dataSnapshot, String s) {
Log.v("DS",dataSnapshot.getValue().toString());
Tables values=dataSnapshot.getValue(Tables.class);
Log.v("isAl", values.toString());
int Capacity=values.getCapacity();
String Customer=values.getCustomer();
boolean IsAllocated= values.isAllocated();
Log.v("isAl", String.valueOf(values.isAllocated())+"\t"+Customer+"\t"+Capacity);
String key = dataSnapshot.getKey();
oldKey=key;
mKeys.add(key);
Tables table=new Tables(Capacity,Customer,IsAllocated);
});
}
My Tables Class is as follows:
public class Tables {
private int Capacity;
private String Customer;
private boolean IsAllocated;
public Tables(int capacity, String customer, boolean isAllocated) {
Capacity = capacity;
Customer = customer;
IsAllocated = isAllocated;
}
public Tables() {
}
public int getCapacity() {
return Capacity;
}
public void setCapacity(int capacity) {
Capacity = capacity;
}
public String getCustomer() {
return Customer;
}
public void setCustomer(String customer) {
Customer = customer;
}
public boolean isAllocated() {
return IsAllocated;
}
public void setAllocated(boolean allocated) {
IsAllocated = allocated;
}
}
Here is my BindViewHolder of Adapter Class:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
list=Tlist.get(position);
Log.v("vlist", String.valueOf(Tlist.get(position)));
holder.tabletext.setText("Table");
holder.status.setText(String.valueOf(list.isAllocated()));
}
In values object, I am getting null values. Any help will be appreciated. Thank you in advance.
Change your class variable it uses a case-sensitive you are using small char and your Firebase DB contains capital
change your class to:
public class Tables {
int Capacity;
String Customer;
Boolean IsAllocated;
And use ValueEventListener to get all the records in single bunch
myRef.child("Tables").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Tables values=dataSnapshot.getValue(Tables.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Edit 1: you can get value using map try below code
myRef.child("Tables").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Map<String,String> map=(Map<String,String>)postSnapshot.getValue();
String Customer=map.get("Customer");
String IsAllocated= map.get("IsAllocated");
String Capacity= map.get("Capacity");
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

How do I rework these Firebase ValueEventListeners to be readable?

If there's something I'm struggling with it's how to write good looking code with asynchronous calls to Firebase. Below is the code for one of my functions that retrieves all users and the current user from Firebase and checks the distance between their chosen locations.
I can't really move each of the ValueEventListeners to separate functions since they all have to fire in succession.
How do I make this code look good?
private void getUsersToDisplay() {
// Get users to display from firebase
Log.w(TAG, "User fetch initialized");
DatabaseReference currentUserRef = mDatabase.getReference().child("users/" + mCurrentUser.getUid());
// Get current user from firebase
currentUserRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot currentUserSnapshot) {
// Get the users chosen location for use in distance calculation
final Double currentUserChosenLatitude =
Double.parseDouble(currentUserSnapshot.child("chosen_location/latlng/latitude").getValue().toString());
final Double currentUserChosenLongitude =
Double.parseDouble(currentUserSnapshot.child("chosen_location/latlng/longitude").getValue().toString());
DatabaseReference usersRef = mDatabase.getReference().child("users");
// Get all users from firebase
usersRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot allUsersSnapshot) {
// For all users in firebase
for (DataSnapshot userSnap : allUsersSnapshot.getChildren()) {
String userId = userSnap.getKey();
DatabaseReference userRef = mDatabase.getReference().child("users/" + userId);
// If the user isn't the current user
if (!userId.equals(mCurrentUser.getUid())) {
// Get the user's info from firebase
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot userSnapshot) {
Double userChosenLatitude =
Double.parseDouble(userSnapshot.child("chosen_location/latlng/latitude").getValue().toString());
Double userChosenLongitude =
Double.parseDouble(userSnapshot.child("chosen_location/latlng/longitude").getValue().toString());
float[] results = new float[1];
Location.distanceBetween(
currentUserChosenLatitude,
currentUserChosenLongitude,
userChosenLatitude,
userChosenLongitude,
results);
// If the user is within 10km of the current user, display it
if (results[0] < 10000) {
users.put(userSnapshot.getKey(), (String) userSnapshot.child("first_name").getValue());
mUserAdapter.add((String) userSnapshot.child("first_name").getValue());
Log.w(TAG, "User to display fetch complete");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "User to display fetch cancelled");
}
});
}
}
Log.w(TAG, "Users fetch completed");
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "Users fetch cancelled");
}
});
Log.w(TAG, "Current user fetch complete");
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "Current user fetch cancelled");
}
});
}
I write my code like this so it easier to read:
onCreate() {
dataRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
doSomething(dataSnapshot);
...
}
...
}
}
doSomething(DataSnapshot dataSnapshot) {
...
}
If I want a Firebase call to run after another Firebase call, I place it inside doSomething.
BUT, if that call doesn't have to run after each other (like "get current user" and "get all user" call from your sample code), I made it like this:
boolean firstCallDone = false;
boolean secondCallDone = false;
DataSnapshot firstDataSnapshot = null;
DataSnapshot secondDataSnapshot = null;
onCreate() {
firstRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
firstCallDone = true;
firstDataSnapshot = dataSnapshot;
if (firsCallDone && secondCallDone)
doSomething();
}
...
}
secondRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
secondCallDone = true;
secondDataSnapshot = dataSnapshot;
if (firsCallDone && secondCallDone)
doSomething();
}
...
}
}
doSomething() {
// do something with firstDataSnapshot and secondDataSnapshot
...
}
Hope this help.

Categories

Resources