Is there another equivalent of Timer for android which is thread safe?
Using the timer causes problems in my application while updating the gui, most of the time it complains that gui is being updated from another thread, i tried using handlers but that didn't fix the problem.
Use postDelayed() on any of your Views. Have it do its work then call postDelayed() again.
Or, use runOnUiThread() instead of messing with your own Looper/Handler.
Or, create your Handler as a private data member of the class with an ordinary initializer -- it would appear you are trying to create it in the background thread, which will not work.
Related
I recently saw an example of a stopwatch app , where the developer used a handler object to update the time displayed on a TextView. Why not use an ordinary loop that keeps on updating the text instead of using a handler?
Every app has its own special thread that runs UI objects such as View objects; this thread is called the UI Thread.
Considering your stopwatch example if you just add the loop inside your activity and keep the time going then it will block your UI thread and your app may become unresponsive. To overcome this problem and not to block the UI/Main thread we use separate threads to do such ongoing/long tasks.
So what he does is created a Handler which will do the long running task and it sends the update to UI thread to update textView when required.
Can I use runOnUiThread() inside a thread to update the user interface while running the thread, or handler is more efficient ? .
Yes you can use runOnUiThread() from a non UI thread to update the UI. That method uses a handler internally if you are not currently on the UI thread so using your own handler will not be more efficient. If you are already on the UI thread then the runnable will be executed immediately.
Efficiency isn't a big deal here. Handler might be useful if you need to call another class (for instance, if your thread runs in a class and you need to update the fragment). If you're in a fragment/activity and have access to the elements you need to update, then it may be easier to do runOnUIThread. It's all about code access really.
I personally use callbacks.
According to the documentation one of three options should be used for accessing the UI thread from a different thread.
These are the options:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
When should I use which? They all seem to add a Runnable to the message queue of the UI thread.
I assume postDelayed is only really useful if you want to schedule a Runnable for later and they only mentioned it because it also runs the Runnable on the UI thread.
And for extra confusion there is also AsyncTask. When should I use that now?
runOnUiThread and View.post are exactelly the same they both send a runnable object to the activity's Handler . so use whichever you like.
Regarding the AsynchTask it is not used to run on the UI thread. but after an Asynch task finishes working it calls a method called OnPostExcute on the UI thread.
There is a very great tutorial on this subject Here
If you need a mechanism for returning to the UI thread that is available from everywhere without needing a context, you can use this:
Handler handler = new Handler(Looper.getMainLooper());
handler.post(Runnable);
I always choose runOnUiThread, I think so is the best way to run something on the same UI Thread.
AsyncTasks are tricky, it's a good idea but if you want to use something new, use loaders or IntentService.
Forget about AsyncTask, it's not for running code in the UI thread, but running code in a background thread starting the AsyncTask from the UI thread.
Regarding the other options, feel free choosing any of them. If you are dealing with a View object, it is likely you are already on the UI thread. Therefore, you better keep a reference to the Activity context from the other thread and call runOnUiThread.
I will recommend you to use AsyncTasks, they were designed to do hard work in other thead (doInBackground()) and then syncronize with UI thead to push work results (onPostExecute()), and of course you can periodically update UI with work progress (onProgressUpdate()).
If you want to run more than one AsyncTask concurrently on Android Version greater than HONEYCOMB, you can use my small lubrary: Android-AsyncTask-Executor
I am updating an activity's UI from a BroadcastReceiver that I register in the same activity. The API docs say:
[...] The function [onReceive()] is normally called within the main thread
of its process [...]
so I suppose updating the UI is okay.
The docs also say:
[...] you should never perform long-running operations in it (there is
a timeout of 10 seconds [...]
I am just setting some text on a TextView so I suppose that won't ever take longer than 10 seconds.
But, and here comes finally my actual question: Does it make any sense at all to add a Runnable to the main thread's message queue using a Handler, so that onReceive() can return immediately and the UI update happens at some later point in time, as the docs suggest:
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; [...]
?
If you're just setting text on TextViews then you won't have issues. No need to over-complicate things with Handlers.
Though I will say that some people like using handlers just because it keeps things organized if multiple calls to a specific UI method need to be called. Using a handler will guarantee that that executed code will be initially placed on the UI thread, so it avoids having to check which thread you are running on.
The important thing to keep in mind is that all UI actions should be performed on the UI thread, and any sort of intensive processing should be done on a background thread.
Yes, using a Handler to schedule a Runnable is the standard.
Is it possible to execute an AsyncTask from Runnable? in my experience it can be done, but not safely. When my app first runs my AsyncTask runs fine from the Runnable. But when the app is moved to the background, then brought back forward I get "Can't create handler inside thread that has not called Looper.prepare()".
Here's what I'm trying to do:
I'm using MapView and invoking runOnFirstFix(Runnable) within onCreate. My Runnable calls an AsyncTask to perform a web service call which returns some data based on the location.
I move the app to the background (by tapping the home button), after some time I bring my app forward again and I'm getting the exception at the point where I'm invoking execute() on my AsyncTask.
First of all, why is runOnFirstFix being executed again? Secondly, why is it causing the exception the second time around?
I'm guessing that there is some part of the lifecycle that I don't understand.
Thanks.
It wasn't initially obvious to me that the AsyncTask needed to be called from the UI thread. So when runOnFirstFix ran the second time it was from withing a Runnable which wasn't on the UI thread. To solve the problem I simple created another Runnable inside the first to run the AsynchTask.
And the reason my runOnFirstFix seemed to be called twice was simply because I was creating a new instance of it.