I have a collection within another (CollectionGroup) and now I want to read a specific object from it. Currently I'm trying as shown below, but I'm not getting any result:
db.collectionGroup("Objekte")
.whereEqualTo("timestamp",key.toString())
.get()
.addOnSuccessListener { doc->
for (document : doc) {
if(document != null)
{
Log.d("TAG", "DocumentSnapshot data: ${document.data}")
} else{
Log.d("TAG", "No such document")
}
}
}
TIMESTAMP LOGOUT:
TIMESTAMP:1672216119769
Related
I am trying to get records from firebase database and return all the record within a array list but inside the for loop it will add records but when we check outside the loop it does not contain records. can anyone please help me i am new in android.Here is the code for fetching data..
public class DataBaseManagement {
public static ArrayList<Property> getAllProperties(Context context, DatabaseReference dbProperty){
ArrayList<Property> propertyList = new ArrayList<Property>();
dbProperty.get().addOnSuccessListener(new OnSuccessListener<DataSnapshot>() {
#Override
public void onSuccess(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
Property tempProp;
for (DataSnapshot aProp: dataSnapshot.getChildren())
{
tempProp = aProp.getValue(Property.class);
propertyList.add(tempProp);
}
Toast.makeText(context, "Total Properties : " + propertyList.size(), Toast.LENGTH_SHORT).show(); // Here it will show the number of records
}
else {
Toast.makeText(context, "No record found", Toast.LENGTH_SHORT).show();
}
}
});
Toast.makeText(context, "Total Properties : " + propertyList.size(), Toast.LENGTH_SHORT).show(); // here it will not show the number of records
return propertyList;
}
}
as I know in addOnSucessListener it works in background thread
the fun will return and finish the background thread I think if you want it change return fun to void and use out fun liveData and update it inside addOnSucessListener
I have the following method:
public static void getRecipe(DocumentReference DR){
Recipe r = new Recipe();
/*First Firestore Query! - Get the recipe*/
DR.get().addOnCompleteListener(task -> {
if (task.isSuccessful() && task.getResult() != null) {
r.addStuff(...);
r.addMoreStuff(...);
r.addEvenMoreStuff(...);
/*Second Firestore Query(s)! - Get the ingredient(s)*/
for(DocumentReference DR_ingredient : ingredients) {
Task<DocumentSnapshot> IngredientQuery = DR_ingredient.get();
IngredientQuery.addOnCompleteListener(t -> {
if (t.isSuccessful() && t.getResult() != null) {
/*even more stuff*/
}
});
}
//After all tasks are finished, we can finally put the recipe in our Database!
Task<Void> t = Tasks.whenAll(IngredientQueries);
t.addOnSuccessListener(unused -> {
addRecipe(r);
});
}
});
}
The method uses Firestore to get a saved recipe and furthermore load the ingredients for the selected recipe. The ingredients are saved as a reference inside of the recipe and must be loaded again per Firebase.
My Question now is: If I call getRecipe(DocumentReference DR) from another class, how can I wait until everything is loaded and then continue with my code?
This is the code I am using but I could not able to update values in firebase..
Database level is like:
users-> userID: fname,phone,country
I am trying to update phone number and name. I am using firebase authentication.
DatabaseReference reference;
onCreate{ encloded in
reference = FirebaseDatabase.getInstance().getReference("users").push();
public void updateProfile(View view) {
if (isNameChanged() || isPhoneChanged()) {
//Toast.makeText(this, "Updated Successfully", Toast.LENGTH_SHORT).show();
} else Toast.makeText(this, "No Change Observed", Toast.LENGTH_SHORT).show();
}
private boolean isPhoneChanged() {
if (!pphone.equals(e_pphone.getText().toString())) {
reference.child(userID).child("phone").setValue(e_pphone.getText().toString());
pphone=e_pphone.getText().toString();
return true;
} else
return false;
}
private boolean isNameChanged() {
if (!pname.equals(e_pname.getText().toString())) {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if(firebaseUser!=null) {
reference.child(userID).child("fname").setValue(e_pname.getText().toString());
pname = e_pname.getText().toString();
Toast.makeText(this, userID, Toast.LENGTH_SHORT).show();
}
return true;
} else {
Toast.makeText(this, "NOOOO "+pname, Toast.LENGTH_SHORT).show();
return false;
}
}
Hy, as you're referencing new path every time i.e.
FirebaseDatabase.getInstance().getReference("users").push();
here push() will generate new value not one which already exist in your database.
as a result dataRef won't get a path and it won't update any information.
reference = FirebaseDatabase.getInstance().getReference("users").push();
instead of push() try with any static data first and then you'll get the idea where the actual problem is.
Finally retrieve the node value which you want to update that you'll be using after "users" in firebaseReference.
This question already has answers here:
How to return a DocumentSnapShot as a result of a method?
(2 answers)
Closed 3 years ago.
Currently Running into an issue where I'm fetching data from firebase. I know it is because Firebase is asynchronous, so when I make my firebase call, it is executed on its own thread, and the current thread that it was called on continues to execute. I'm populating a list of objects with the data from firebase and I return that list of objects. The thing is, the list is always returning null because the execution of the firebase code isn't completed in time.
I created some asynchronous code that fetches from SQLite db that works fine, but this approach does not seem to work with firebase (I believe its due to firebases API being asynchronous) Here is my method to return a list of objects from firebase.
/** Method to get activity data from firebase.
* #param userInput the user query to select the data
* #return a list of activity models based on the query
* */
public List<ActivityModel> retrieveActivityData(String userInput) {
Log.d(TAG, "retrieveActivityData: starts");
List<ActivityModel> models = new ArrayList<ActivityModel>();
// execute the query in firebase
CollectionReference activfitCollection = db.collection("activity");
activfitCollection.orderBy("isoTimestamp")
.startAt(userInput)
.endAt(DateHelper.getDayEndingDate(userInput))
.get()
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Log.d(TAG, "onComplete: Getting data successful!");
// check to see if it exists
if (!task.getResult().isEmpty()) {
for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
Log.d(TAG, "retrieveActivityData: document = " + documentSnapshot.getId());
// cast the document to the activity model
Log.d(TAG, "retrieveActivityData: document data " + documentSnapshot.getData());
ActivityModel model = mapToActivityModel(documentSnapshot);
models.add(model);
Log.d(TAG, "retrieveActivityData: array size" + models.size());
}
}
} else {
Log.e(TAG, "onComplete: Error getting documents: ", task.getException());
}
});
Log.d(TAG, "retrieveActivityData: array size outside " + models.size());
return models;
}
Option - 1: You can use LiveData to achieve this. Post value to LiveData when operation complete and observe that inside your activity or fragment
MutableLiveData<List<ActivityModel>> listMutableLiveData = new MutableLiveData<>();
public MutableLiveData<List<ActivityModel>> retrieveActivityData(String userInput) {
List<ActivityModel> models = new ArrayList<ActivityModel>();
....
if (task.isSuccessful()) {
for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
....
models.add(model);
}
//Post value to live data from here
listMutableLiveData.postValue(models);
}
....
return listMutableLiveData;
}
And then observe like this
retrieveActivityData(userInput).observe(this, new Observer<List<ActivityModel>>() {
#Override
public void onChanged(List<ActivityModel> activityModels) {
//you can use list here
}
});
Option - 2: You can use callback function to get result when firebase operation complete.
Create an interface for callback
interface FirebaseResultListener {
void onComplete(List<ActivityModel> activityModels);
}
Configure your retrieveActivityData to handle this callback
public void retrieveActivityData(String userInput, FirebaseResultListener callback) {
List<ActivityModel> models = new ArrayList<ActivityModel>();
....
if (task.isSuccessful()) {
for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
....
models.add(model);
}
//Invoke callback with result from here
callback.onComplete(models);
}
....
}
Implement this interface in your activity or fragment
retrieveActivityData(userInput, new FirebaseResultListener() {
#Override
public void onComplete(List<ActivityModel> activityModels) {
//you can use list here
}
});
Since the data is loaded async you cannot return the data, you should pass callback(Interface) in retrieveActivityData method, and use callback of interface to load the data, check the code bellow
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
MyFirebaseCallback myFirebaseCallback = new MyFirebaseCallback() {
#Override
public void dataLoaded(List<ActivityModel> activityModels) {
//set the data in recycler view
}
};
retrieveActivityData("myInput",myFirebaseCallback);
}
public void retrieveActivityData(String userInput, final MyFirebaseCallback callback) {
Log.d(TAG, "retrieveActivityData: starts");
// execute the query in firebase
CollectionReference activfitCollection = db.collection("activity");
activfitCollection.orderBy("isoTimestamp")
.startAt(userInput)
.endAt(DateHelper.getDayEndingDate(userInput))
.get()
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
List<ActivityModel> models = new ArrayList<ActivityModel>();
Log.d(TAG, "onComplete: Getting data successful!");
// check to see if it exists
if (!task.getResult().isEmpty()) {
for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
Log.d(TAG, "retrieveActivityData: document = " + documentSnapshot.getId());
// cast the document to the activity model
Log.d(TAG, "retrieveActivityData: document data " + documentSnapshot.getData());
ActivityModel model = mapToActivityModel(documentSnapshot);
models.add(model);
Log.d(TAG, "retrieveActivityData: array size" + models.size());
}
}
callback.dataLoaded(models);
} else {
Log.e(TAG, "onComplete: Error getting documents: ", task.getException());
}
});
Log.d(TAG, "retrieveActivityData: array size outside " + models.size());
}
interface MyFirebaseCallback{
void dataLoaded(List<ActivityModel> activityModels);
}
You have guessed it right! The query is asynchronous so retrieveActivityData() shouldn't return List<ActivityModel> or it would always be null. You would have to use an Event Bus to fire an event as soon as your List is compiled inside onComplete() or use LiveData and observe it.
LiveData
ViewModel
EventBus
When I was using firebase for initialization of data and setText on UI, It was delayed for 10~15 seconds.
On the other hand, When I use Volley, It was delayed for only 1 seconds.
why is it so slow when i'm using firebase and How can I modifying this code?
here is my code (using ValueEventListener) and JSON tree
"couple_profile" : {
"TEST999AhCBcHK32AQzU3JglVbAxhTD6Mn1" : {
"birthday_1" : "1994-06-29",
"birthday_2" : "19940629",
"couple_nick" : "TEST999",
"exp" : 0,
"gold" : 0,
"level" : 1,
"member" : {
"AhCBcHK32AQzU3JglVbAxhTD6Mn1" : {
"FCM" : "d5Y-fl_0VCs:APA91bHX7HA531PXc1e4clUg61uB3XsKlwmQ_2U9OaESUTP0r-dnwbitSvxQ4EDMqPzK-t_5b9qPOhLm01FRffgB9-Ot6bZmx1JzwZvc07yoyhashGUS79E7Dztr2J7NfR1NGXw1LT2V",
"birthday" : "1994-06-29",
"name" : "김준겸",
"phone_number" : "01050639201"
},
"FMsH7leNTOXBgbOFoWdaTMjt05T2" : {
"birthday" : "19940629",
"name" : "kimGod",
"phone_number" : "1541"
}
},
"mileage" : 0,
"name_1" : "김준겸",
"name_2" : "kimGod",
"uid_1" : "AhCBcHK32AQzU3JglVbAxhTD6Mn1",
"uid_2" : "FMsH7leNTOXBgbOFoWdaTMjt05T2"
}
private void get_home_info() {
valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
coupleProfile = dataSnapshot.getValue(CoupleProfile.class);
if (coupleProfile == null) {
Log.e(TAG, "User " + FirebaseAuth.getInstance().getCurrentUser().getEmail() + " is unexpectedly null_1");
Toast.makeText(Home_Fragment.this.getContext(), "Error_1", Toast.LENGTH_SHORT).show();
} else {
StorageReference storageRef2 = storage.getReferenceFromUrl("FirebaseURL").child("Profile_image/" + FirebaseAuth.getInstance().getCurrentUser().getUid());
Glide.with(getContext()).using(new FirebaseImageLoader()).load(storageRef2).centerCrop()
.bitmapTransform(new CropCircleTransformation(new CustomBitmapPool()))
.into(me_view);
SharedPreferences.Editor sh = home_info.edit();
if (My_UID.equals(coupleProfile.uid_1)) {
my_number = 1;
sh.putString("my_name",coupleProfile.name_1);
sh.putString("op_name",coupleProfile.name_2);
sh.apply();
my_name_text.setText(coupleProfile.name_1);
op_name_text.setText(coupleProfile.name_2);
state_text.setText(coupleProfile.state_1);
op_state_text.setText(coupleProfile.state_2);
StorageReference storageRef = storage.getReferenceFromUrl("FirebaseURL").child("Profile_image/" + coupleProfile.uid_2);
Glide.with(getContext()).using(new FirebaseImageLoader()).load(storageRef).centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.bitmapTransform(new CropCircleTransformation(new CustomBitmapPool()))
.into(friend_view);
} else if (My_UID.equals(coupleProfile.uid_2)) {
my_number = 2;
sh.putString("my_name",coupleProfile.name_2);
sh.putString("op_name",coupleProfile.name_1);
sh.apply();
my_name_text.setText(coupleProfile.name_2);
op_name_text.setText(coupleProfile.name_1);
state_text.setText(coupleProfile.state_2);
op_state_text.setText(coupleProfile.state_1);
StorageReference storageRef = storage.getReferenceFromUrl("FirebaseURL").child("Profile_image/" + coupleProfile.uid_1);
Glide.with(getContext()).using(new FirebaseImageLoader()).load(storageRef).centerCrop().diskCacheStrategy(DiskCacheStrategy.SOURCE)
.bitmapTransform(new CropCircleTransformation(new CustomBitmapPool()))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(friend_view);
} else {
Log.e(TAG, "User " + FirebaseAuth.getInstance().getCurrentUser().getEmail() + " is unexpectedly null_2");
Toast.makeText(Home_Fragment.this.getContext(), "Error", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "onCancelled: ", databaseError.toException());
}
};
ref = databaseReference.child("couple_profile").child(room_token);
ref.addValueEventListener(valueEventListener);
}
I think if you use this method from firebase you will have better loading of data:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Use the above code, explanation about it:
Firebase provides great support when comes to offline data. It automatically stores the data offline when there is no internet connection. When the device connects to internet, all the data will be pushed to realtime database. However enabling disk persistence stores the data offline even though app restarts.
Also try and retrieve the data in onStart()
Also, look for uses of .keepSynced(true). This likewise causes the entire node for which it is called to be fetched before it makes any updates. This can be very slow, depending on what node it is called for.