I am a beginner in android application development.I am working with threads in android.I have read about a runOnUiThread which run code on main UI(if i am not wrong?i guess.).
My question is what is the difference between normal code on main UI and code inside runOnIUThread.
Example:1
class A
{
getDataFromServer(foo);//Code on mainUI
}
Example:2
getActivity.runOnUiThread(new Runnable(){
#Override
public void run(){
getDataFromServer(foo);
}
});
What is difference in both example.Please help me.Your response will be a new learning for me.
Assuming that you meant simple code for UIThread code,
What is a thread ?
A thread defines a process running
First runOnUiThread ..
Runs the specified action on the UI thread. If the current thread is
the UI thread, then the action is executed immediately. If the current
thread is not the UI thread, the action is posted to the event queue
of the UI thread.
What is UIThread
Main thread of execution for your application
Most of your application code will run here onCreate, onPause, onDestroy, onClick, etc.
So simply Anything that causes the UI to be updated or changed HAS to happen on the UI thread
When you explicitly spawn a new thread to do work in the background, this code is not run on the UIThread.Now what if you want to do something that changes the UI?
Then you are welcome to runOnUiThread
You have to use runOnUiThread() when you want to update your UI from a Non-UI Thread. For eg- If you want to update your UI from a background Thread. You can also use Handler for the same thing.
Normally your code is executed on your UI thread. For longer taking tasks (such as network requests, etc...) you will use a background tasks (Handler, AsyncTask, Thread, ...).
As your Views can only be touched from a UI thread, you use runOnUiThread() if you are executing code in a background thread and you need to update your views, from this background thread.
To explain 'why' Android has the 'runOnUiThread()' option, it is important to understand that java is only used to create the bytecode (dex) that Android uses. The code running on the phone is NOT java.
Additionally, Android threads 'can' have a thing called a 'looper'. This 'looper' is what handles 'tasks(technically runnables and messages)' in order via a queue. The 'main ui thread' has by default a looper already attached to it.
That means that your runnable you created was put onto the looper's queue of the main UI thread. (this is why the runnable is NOT instantaneously ran, but will be ran 'quickly'/'soon')
The reason you'd use a runnable to run code on the UI thread is because you are in some other 'background thread' that you created... and want to update the UI in some way. (Only the UI thread can interact with the UI)
Related
This question already has answers here:
How do we use runOnUiThread in Android?
(13 answers)
Closed 4 years ago.
In following code
The way we are using runOnUiThread
shouldn't this create issue with the existing UI Thread
hence creating an issue with the application , hence shouldnt be used
Thread thread = new Thread(new Runnable(){
#Override
public void run(){
//what is meant by the inside code of this run(), how is this updating the UI
runOnUiThread(new Runnable(){
#Override
public void run(){
}
})
}
})
In android,for long running task you should use separate thread such as AsyncTask() or service.Suppose you want to update your UI like you want to show any Toast to user then you should write runOnUiThread(),because only UI thread will allow to touch UI components.
getActivity().runOnUiThread(new Runnable()
{
#Override
public void run() {
Toast.makeText(getContext(), "API calling done!!", Toast.LENGTH_LONG).show();
}
});
There are two types of thread in Android.
1 is UI or Main thread on which your UI elements (layouts) are rendered.
2 is Worker Thread in which long task should be executed (like AsyncTask & Networking).
If you write some task in new Thread, that mean that task will be executed in worker thread.
Now you will use runOnUiThread or new Handler(Looper.getMainLooper()) because you can not touch UI elements in worker thread.
So basically when you are updating UI like setText(), or Toast or any UI operations, you will have to UI thread and you should use worker thread when you are doing some long executions.
Edit
Generally we don't have to manage threading in Android. Because all libraries we use are smart. Although in some cases we have to manage threading as well.
Example
Assume you are calling an web-service(api) in a new Thread, now when response comes you want show a Toast. If you just write Toast.show... directly in response inside worker Thread you will get exception.
Only the original thread that created a view hierarchy can touch its views.
Now to overcome this issue you have to use runOnUiThread, so that you can show Toast.
Whenever we have some Long running tasks we switch to some worker threads and avoid Main Thread and allow a smoother user experience and avoid ANR.
But, when the time comes to update the UI we must “return” to the
Main Thread, as only Main Thread is allowed to touch and update the application
UI.
we can achieve this by making a call to the Activity’s runOnUiThread() method:
Basically what runOnUiThread() will do is - Runs the specified action
on the UI thread. It will check the current thread and if it finds its
the MainThread it will execute that task immediately , otherwise first
it will switch you to app MainThread and then it will execute the
given task.
When a new Thread is created and executed, it does the task in the background thread. But the method runOnUiThread() is used for running the code on the main UI thread.
In your code, runOnUiThread() method is called and hence you are able to update the UI thread from the other thread.
when thread is running in the method runOnUiThread () will update the UI Components (textview .. etc..)
by calling runOnUiThread, you can update the status too
shouldn't this create issue with the existing UI Thread
Not at all. You said "existing UI Thread". There is only one UI thread. The runOnUiThread() will only add the runnable to a queue of tasks which the UI thread executed one by one. You can check the doc.
No worries! This is one of the standard way for updating UI components from a separate thread or even on UI thread itself on Android platform.
Also, runOnUiThread is an method of Activity class, it runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread.
Another standard way is using Handler and Message as officially documented by Android Developer here https://developer.android.com/training/multiple-threads/communicate-ui
I have a bunch of AsyncTasks and their callbacks (listener interfaces) that I dont want to have anything to do with the UI thread.
Reading the answer here: Android : can AsyncTask return in another thread than UI thread?
I am left with the impressin that I can only start AsyncTasks from the UI Thread which means the callbacks that I invoke from their onPostExecute methods will also be in the main thread.
How do I move all this logic away from the UI thread?
First, based on some issues I've had before when trying to run AsyncTasks in an IntentService, I think your assumption that you cannot run an AsyncTask from a non-UI thread is false.
The problem I've found with starting AsyncTasks off the UI thread is not that they don't run or that they cause crashes, but that onPostExecute() doesn't automatically run on the main UI thread after the other stuff finishes. I wouldn't recommend doing it, but you probably could if you wanted to.
But the whole reason AsyncTasks exist are basically to have an easy way to run some code off the UI thread and then be able to alter UI stuff after it's finished. So if you don't want to do anything at all with the UI thread, you shouldn't need to use an AsyncTask at all. If you don't need to run any code on the UI thread, you can just use something like:
new Thread(new Runnable() {
public void run() {
//Do your stuff
}
}).start();
I have a thread which is started in onCreate() and this thread fetches some data.
Is it possible that before the thread is terminated should be able to update the ListView?
Now as the thread is not the UI thread, it cannot directly update the listview array adapter.
Is there a way out?
I was thinking that is it possible to trigger a Handler from thread whose runnable gets executed on main UI thread.
Not sure if I understood your problem completely, but I believe there are two ways to achieve what you want:
1- Start an AsyncTask instead of a thread. AsyncTask's onPostExecute() will run in the UI thread, which means you can do anything UI-related in there. You can start the AsyncTask in onCreate(), and, once it finished, it calls a method on your activity which does:
myAdapter.notifyDataSetChanged();
2- Use runOnUIThread()
Use your Activity's runOnUiThread(Runnable action)
link
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
Can someone explain to me what exactly the UI thread is?
On developer.android.com it says about the runOnUiThread function
public final void runOnUiThread (Runnable action)
Since: API Level 1 Runs the specified action on the UI thread. If the
current thread is the UI thread, then the action is executed
immediately. If the current thread is not the UI thread, the action is
posted to the event queue of the UI thread.
Does the UI thread mean that this will be run everytime the activity is pushed the the background by some ui activity like incoming call or screen dimming etc.? If not, what exactly does the UI thread include ?
Thank you
The UIThread is the main thread of execution for your application. This is where most of your application code is run. All of your application components (Activities, Services, ContentProviders, BroadcastReceivers) are created in this thread, and any system calls to those components are performed in this thread.
For instance, let's say your application is a single Activity class. Then all of the lifecycle methods and most of your event handling code is run in this UIThread. These are methods like onCreate, onPause, onDestroy, onClick, etc. Additionally, this is where all of the updates to the UI are made. Anything that causes the UI to be updated or changed HAS to happen on the UI thread.
For more info on your application's Processes and Threads click here.
When you explicitly spawn a new thread to do work in the background, this code is not run on the UIThread. So what happens if this background thread needs to do something that changes the UI? This is what the runOnUiThread is for. Actually you're supposed to use a Handler (see the link below for more info on this). It provides these background threads the ability to execute code that can modify the UI. They do this by putting the UI-modifying code in a Runnable object and passing it to the runOnUiThread method.
For more info on spawning worker threads and updating the UI from them click here
I personally only use the runOnUiThread method in my Instrumentation Tests. Since the test code does not execute in the UIThread, you need to use this method to run code that modifies the UI. So, I use it to inject click and key events into my application. I can then check the state of the application to make sure the correct things happened.
For more info on testing and running code on the UIThread click here
If you execute blocking code (e.g. a Http-Request) in a separate Thread, consider using AsyncTask. Its doInBackground-Method runs on a separate Thread. AsyncTask provides you with methods onProgressUpdate and onPostExecute which are guaranteed to run on the UI thread.
If you need GUI-progress updates (e.g. via a progressbar) call publishProgress inside doInBackground. This leads to a subsequent call of onPublishProgress which is also guaranteed to run on the UI thread.
onPostExecute is automatically called after doInBackground returns.
All UI drawings etc. happen in a separate thread. Its called the UIThread. If you want to make any change to UI u must use make sure it happens in UIThread's context.
Easiest way of doing it is to make use of runOnUiThread