Using Java - Firebase Admin SDK.
I have to make two updates on the Firebase Realtime Database. Update#1 has to happen and only then Update#2 should happen.
I was earlier using this :
ref.setValueAsync("update#1");
ref.setValueAsync("update#2");
But in very rare cases - update#2 was happening before update#1 - flow was breaking for our usecase; I refactored the code to this :
ref.setValue("update#1", null);
ref.setValueAsync("update#2");
This change was made with the assumption that setValue is a sync call and we will only go for update#2 once update#1 is done. But we have noticed that cases of update#2 happening before update#1 are still there - although very rare.
But in very rare cases - update#2 was happening before update#1
That's the expected behavior since the operations run in parallel. So there can be cases in which the second operation completes faster than the first one. So simply calling an operation right after the other doesn't offer you any guarantee of the order in which the operations will complete.
If you need to perform the second operation, only when you're 100% sure that the first operation is complete, then you have to pass to setValue() method the actual data and a completion listener:
ref.setValue("data", new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError error, DatabaseReference dataRef) {
if (error != null) {
System.out.println("Failed because of " + error.getMessage());
} else {
//Perform the second operation.
}
}
})
So as soon as the first operation completes, inside the callback perform the second one.
Related
I'm using firebase in my app and most of the time it writes the values on the firebase entry with this instruction.
ref.setValue(result);
But on some rare occasions value is not written.
So I have thought about doing this:
boolean finished=false;
[...]
t=new Thread(new Runnable() {
#Override
public void run() {
while (!finished)
{
ref.setValue(result, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
finished=true;
}
}
});
t.sleep(50);
}
});
t.start();
As most of the time the data is written successfully, it looks like even if an error where to happen when wrting data, it would end up being written successfully anyway.
But maybe this is not enough to ensure that the data ends up being written and it may cause an infinite loop, getting one database error after another.
Is this a good approach to solve the problem?
The Realtime Database client already runs all network operations in a background thread. This means that all operations take place without blocking your main thread. Trying to create a new Thread, does not give any benefits at all. Besides that, trying to use:
t.sleep(50);
Might work, if the request takes less than 50 milliseconds. How about 51? That's not how you should deal with asynchronous operations. However, the solution is always the same. Any code that needs to be used when the write operation completes, needs to be inside the onComplete method, or be called from there. If you want to learn how to handle asynchronous operations, I recommend you check my answer from the following post:
How to return DataSnapshot value as a result of a method?
If you understand Kotlin, I also recommend you read the following article:
How to read data from Firebase Realtime Database using get()?
I would say no this is not a good solution, a better solution would be a counter and a maximum number of retries say 10 this removes the risk of an infinite loop in the case of constant database errors. While still allowing multiple tries to insert the data correctly into the firebase database.
In my Android app i'd like the user to be able to see when a task is running in the background.
These tasks can be either network calls or database operations, running on separate background threads.
There is a single indeterminate ProgressBar in the Activity, which i would like to show if any background tasks are running, and hide it otherwise.
I've searched for solutions to this and people seem to use LiveData for similar purposes.
So i figured i'd create a LiveData in the ViewModel of the Activity that represents the current loading state of the app, something like this:
val loadingState = MutableLiveData<State>()
Whenever i'm starting or finishing a task, i'd post the appropriate value to this LiveData:
// starting background operation
loadingState.postValue(Status.LOADING)
And i'd observe on it from the Activity and show/hide the ProgressBar according to the current state:
loadingState.observe(this, Observer { status ->
when (status) {
Status.LOADING -> showProgressBar()
Status.IDLE -> hideProgressBar()
}
}
My problem is i don't know how to handle this when there are multiple tasks running on multiple threads.
For example:
A task starts and sets the status to LOADING (correct)
B task starts (the status is already LOADING so nothing happens) (correct)
A task finishes and sets the status to IDLE, however B is still running (wrong)
The ProgressBar will be hidden even though B is still in progress
B task finishes, but the status is already IDLE (wrong)
I thought i could maintain a Collection of LiveData objects (as in a separate LiveData for each task) but it seems really cumbersome.
Is there an idiomatic way to handle this?
(Java answers are welcome as well)
i have a simple idea
in the view model use variable like that
var numberOFThreads = 0
and replace this line
loadingState.postValue(Status.LOADING)
with
if(numberOFThreads == 0){
loadingState.postValue(Status.LOADING)
}else{
numberOFThreads++
}
and
if(numberOFThreads == 0){
loadingState.postValue(Status.IDLE )
}else{
numberOFThreads--
}
Here is a simplified version of my code. function1() has to check something on the internet. It has to do it in the background of the app(I cannot change that), which allows the rest of the code to run while it checks the internet. This function can take several seconds to complete. I cannot put the log at the end of function 1 because it needs to run whether function1 is successful or not, but only after it is done trying. How can I achieve this without using a timer?
if (condition) {
if (condition2) {
function1();
}
Log.i("Info", "This should not appear until function1 completes or fails");
}
Don't constantly check; this is called busy waiting and is inefficient, especially on mobile (since the device can't go into low-power mode). Instead, use an AsyncCallback to run your function1 and put the log message in the callback.
Right now, I have a piece of code that contacts another server asking if an item is in a list, and returns a boolean value based on that returned value.
The code goes like so:
public boolean checkIfOnline(int accountId) {
//First loop is incase if someone is already checking. Second is for the checking that this account is doing.
while (isCheckingIfOnline) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
}
}
isCheckingIfOnline = true;
sendCheckIfOnline(accountId);
while (isCheckingIfOnline) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
}
}
return onlineResponse;
}
The onlineResponse and isCheckingIfOnline are changed within a method that handles what the other server returns, and this is the method I've thrown together to have the system wait for the other server to respond. Obviously, this is very flawed, as when this method gets called often, it'll slow down the system since it only allows for one query at a time, when it should allow for multiple queries to be executed simultaneously.
What other method could I use that accomplishes what the above code does, but allows for more than one query to run at once?
Edit: To clarify even more, checkIfOnline takes an account ID, and asks another server is that account ID is on a list, which that other server responds to the current server if the account ID is or is not on the list.
Sounds like you would want to make use of the ExecutorService in Java 6+.
The ExecutorService requires you to submit to it a class that implements Callable. When you submit a Callable to a ES, you receive back a Future that you can use to do a number of things, including cancelling the process or getting a result from a completed process.
It's a little hard for me to understand exactly what you are trying to achieve with your code and why you're threading that particular part. That being said, if you want to achieve concurrency there, you'd have to:
submit a Callable to the ES that does the online checks & query;
provide a way for the Callable to notify the your application that it has finished it's execution.
It will not be sufficient to simply submit the task and call Future.get() on it because whatever thread makes that call will be suspended until the task is completed.
You'd need to either allow the Callable to invoke a callback, or thread the class that performs the submission of the task and allow it to sit and wait for the future.get() method to return a result.
Good luck :)
This application I've been working on has databases with multiple megabytes of data to sift through. A lot of the activities are just ListViews descending through various levels of data within the databases until we reach "documents", which is just HTML to be pulled from the DB(s) and displayed on the phone. The issue I am having is that some of these activities need to have the ability to search through the databases by capturing keystrokes and re-running the query with a "like %blah%" in it. This works reasonably quickly except when the user is first loading the data and when the user first enters a keystroke. I am using a ResourceCursorAdapter and I am generating the cursor in a background thread, but in order to do a listAdapter.changeCursor(), I have to use a Handler to post it to the main UI thread. This particular call is then freezing the UI thread just long enough to bring up the dreaded ANR dialog. I'm curious how I can offload this to a background thread totally so the user interface remains responsive and we don't have ANR dialogs popping up.
Just for full disclosure, I was originally returning an ArrayList of custom model objects and using an ArrayAdapter, but (understandably) the customer pointed out it was bad memory-manangement and I wasn't happy with the performance anyways. I'd really like to avoid a solution where I'm generating huge lists of objects and then doing a listAdapter.notifyDataSetChanged/Invalidated()
Here is the code in question:
private Runnable filterDrugListRunnable = new Runnable() {
public void run() {
if (filterLock.tryLock() == false) return;
cur = ActivityUtils.getIndexItemCursor(DrugListActivity.this);
if (cur == null || forceRefresh == true) {
cur = docDb.getItemCursor(selectedIndex.getIndexId(), filter);
ActivityUtils.setIndexItemCursor(DrugListActivity.this, cur);
forceRefresh = false;
}
updateHandler.post(new Runnable() {
public void run() {
listAdapter.changeCursor(cur);
}
});
filterLock.unlock();
updateHandler.post(hideProgressRunnable);
updateHandler.post(updateListRunnable);
}
};
I find it difficult to believe that listAdapter.changeCursor() alone would take up sufficient time to cause an ANR, assuming you created the Cursor in a background thread. There just should not be that much work that needs to happen to repaint a handful of list rows. I would double-check to see what work you are doing in your Handler is as limited as you think. Perhaps consider using an AsyncTask, which makes it easier to separate the background work (doInBackground()) from the on-UI-thread post-processing (onPostExecute()).
You can try just replacing the adapter outright, by calling setAdapter() again with the new Cursor wrapped in a new adapter.
You can look to see how AutoCompleteTextView handles this scenario, since it does on-the-fly filtering with a SpinnerAdapter. Perhaps some of its techniques can apply in your case.
Just posted an answer here: Android: Update Listview after Thread loads data from the net
Short: AsyncTask's method onProgressUpdate can touch the view: http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)