Despite Android being a multi-threaded, some API classes impose a strict requirement of having to only run on the UI thread.
For example,
All SpeechRecognizer's methods "must be invoked only from the main application thread."
The Android Developer's Threads section describes components from the android.widget and android.view packages as having to run on the main/UI thread.
According to this SO answer, TextToSpeech constructor also needs to be called from the main/UI thread.
The CountDownTimer must also be created on the UI thread, if its thread does not have a Looper.
Which other classes require their methods runOnUiThread()?
Is there a comprehensive list of such classes in the Android SDK?
Related
I'm using a worker thread in my app so it's vital for me to know which code can be run from the worker thread and which code needs to be run on the UI thread.
In the Android documentation, the following hints can be found:
So, you must not manipulate your UI from a worker thread—you must do
all manipulation to your user interface from the UI thread. [...]
However, note that you cannot update the UI from any thread other than
the UI thread or the "main" thread.
(source)
But what "manipulation to your user interface" means in practice is often not as clear as it seems. Of course, it's clear that you cannot hide views, manipulate button texts, add list view entries, etc. from a worker thread.
But what about calling setRequestedOrientation() from a worker thread, for example? Is that allowed or does it fall under UI manipulation and thus must be called from the UI thread? Is there any way to tell or should I stay safe and better run the code on the UI thread when in doubt?
In general you should take guidance from the API documentation. For example the Activity.onCreate() explicitly states that:
This method must be called from the main thread of your app.
For the example you gave Activity.setRequestedOrientation() there is no explicit statement that the method should be called on a particular thread. Usually if threading is of concern the documentation will state that.
If you would prefer certainty then you called also call upon Activity.runOnUiThread()
According to Android doc,
"...Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread"
That seems very plausible, but is it correct that the compiler does NOT complain at all if a programmer violates the second rule?
You will not get a compile-time error. You may (or may not) get a run-time error.
There are many ways to update UI like
Handler
AsyncTask
runOnUiThread method of View
BroascastReceiver
I have question which puzzles me.
Imagine I wanna do something in another thread, like fetching GPS/Location stuff, which as recommended in the SDK documents, must use a background thread.
So here is the question: What's the difference between
Creating a Thread in background via AsyncTask AND
Creating Thread thread1 = new Thread(new Runnable() ... and implementing run()?
AsyncTask is a convenience class for doing some work on a new thread and use the results on the thread from which it got called (usually the UI thread) when finished. It's just a wrapper which uses a couple of runnables but handles all the intricacies of creating the thread and handling messaging between the threads.
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask.
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
The Runnable interface is at the core of Java threading. The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread.
Also if I quote from this blog:
if you need SIMPLE coding use AsyncTask and if you need SPEED use traditional java Thread.
Key differences:
AsyncTask is an asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. It can't be done with normal thread unless you use Handler on UI Thread and post a message OR directly change attribute of an object by implementing proper synchronization.
As recommended by developer guide regarding Thread performance,
There are a few important performance aspects to keep in mind. First, by default, an app pushes all of the AsyncTask objects it creates into a single thread. Therefore, they execute in serial fashion, and—as with the main thread—an especially long work packet can block the queue. For this reason, we suggest that you only use AsyncTask to handle work items shorter than 5ms in duration..
But normal Thread can be used for long running tasks.
Plain java Threads are not much useful for Android unlike HandlerThread, which has been provided by Android framework.
Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
Refer to below post to know more details:
Handler vs AsyncTask vs Thread
Also take in count that starting on Android v4.04, you can't have more than one AsyncTasks at a time, unless you lose compatibility with lower versions. Be aware!
AsyncTask deprecated with api level 30. Using thread/runnable is convenient
One obvious drawback for AsyncTask class is that after Android 3.0 asynctasks are executed according to the sequence of the start time. that is tasks are executed one by one, unless you execute the task by calling 'executeOnExecutor(Executors.newCachedThreadPool())'. this method would create your own thread pool.
Better to use the new Job Scheduler in the support library.
Quoting the Android developer guide found here here its says
Additionally, the Andoid UI toolkit is not thread-safe. So, you must
not manipulate your UI from a worker thread—you must do all
manipulation to your user interface from the UI thread
What does it mean that the widget's is not thread safe ? What causes the application to crash when we change the name of a Button off the UI Thread. I understand there is a event queue for the UI thread, but how does a separate thread cause issues with this queue ? I tried looking around, and everywhere it says you cannot do it, but no reason why ?
When the documentation says that the UI toolkit is not thread-safe, this means that the UI toolkit is written in such a way that it assumes that all access to UI objects is made from a single thread. By making this assumption, the implementers of the UI toolkit can make unsynchronized access to all the UI objects without fear of data corruption. This makes the UI toolkit easier to implement, easier to test, and improves the performance of the UI toolkit (because it does not need to lock objects before manipulating them).
The UI toolkit is designed to run ONLY on the main thread (otherwise known as the "UI thread"). If you now access UI components from another thread, you run the risk of corrupting the UI toolkit's objects. To ensure that you don't do that, the UI toolkit designers do 2 things:
They write in the documentation that you aren't supposed to access the UI toolkit from outside the main thread
Some (but not all) methods of the UI toolkit check to see if you are making access from outside of the main thread and throw exceptions in such conditions
However, this doesn't forcibly prevent you from accessing the UI toolkit from another thread. In fact, you can probably change the text on a button from another thread without any bad side-effects. That said, you still shouldn't do it. Because in some cases you will cause crashes, in some cases you will find that the changes you make to the UI just get overwritten or ignored, etc.
I hope this makes sense.
The Qt doc says,
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread.
The Android doc says,
Like activities and the other components, services run in the main
thread of the application process
And iOS,
It is strongly recommended not to update UI controls etc from a
background thread (e.g. a timer, comms etc). This can be the cause of
crashes which are sometimes very hard to identify. Instead use these
to force code to be executed on the UI thread (which is always the
“main” thread).
Why does they use a single threaded model to update UI ?
The short answer is, it's the only reasonable way to ensure that the display is not corrupted.
The long answer is that allowing multiple threads to update the UI results in deadlocks, race conditions, and all sorts of trouble. This was the painful lesson taught by Java's AWT (among other UI systems) that allows multiple threads to touch the UI. See, for instance, Multithreaded toolkits: A failed dream?. That post refers (via dead links) to Why Threads Are A Bad Idea and Threadaches.
iOS and Android force you to work with UI only from main thread. The reason is the same as a shared object, thread safe[About]... in multithread environment
Android example error
FATAL EXCEPTION: Thread-19449
E/AndroidRuntime: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views
iOS example error
This application is modifying the autolayout engine from a background thread" error?