Android Runnable and handler on main UI Thread - java

Regarding Java Andriod Handlers:
handler.post(new Runnable(){
public void run() {
// do stuff
}
});
From what i understand this gets run on the whatever thread the handler was instantiated on. so lets say in Android i instantiate the handler on the main thread, my question then is what is the point of the runnable ? your adding a task to the messaging queue of the main UI thread, why not just skip the runnable and create a method since your on the main thread already. I've seen programmers doing this and i want to know why ?
I understand we can do Thread genThread = new Thread(new myRunnable()); but i want to know if there is any value of a Runnable on the main thread.

Sometimes you want to run some code but you don't want it to run immediately, you want to defer it. One of the most common uses for this in my experience is when you are in the layout phase and you want to "queue" up something to happen once the layout phase is done. For this you simply post a Runnable to the UI thread's message queue and it will get put at the end of the message queue...which is exactly where you want it.
Another common use case is if you want to find out the size of a view from onCreate. In onCreate the view hasn't been measured yet so this won't work:
Log.d(TAG, view.getWidth());
Instead you can do this:
view.post(new Runnable() {public void run() {Log.d(TAG, view.getWidth());}}) ;

I would recommend using AsyncTask<> rather than Handlers as they are easier to understand and make for cleaner code. I know that I am diverting from the original question posted but this is just a suggestion. If you want to know more about AsyncTask<> below is the link.
AsyncTask

Related

Correct way to communicate the result of a background thread to the Ui Thread in Android

This is one of the most confusing topics for me. So my question is, what is the correct way of communicate the result of background thread when this finish?.
Imagine I want to update some TextView with some information I just downloaded.There is 3 things I use when I need to perform background tasks:
AsyncTask
Very easy to use, this one has the onPostExecute() method that will return the result directly to the UiThread so I can use a callback interface or do whatever I want. I liked this class but it's deprecated.
ThreadPoolExecutor
This is what I actually use when need to perform background tasks and here comes my problem, the moment when I have to give the result to the UiThread. I have informed myself about Looper and Handler classes and about the mainLooper.
So, when I need to return some results I use the method runOnUiThread() that, as I have readed, just get the Looper of the Ui thread and post my Runnable to the queue.
Well this is working and I can communicate with the main thread but, I find it really ugly, and I am sure there is a more elegant way of doing it than populate all my code of "runOnUiThread()" methods. Also, if the background task need too much time, maybe the user already change of Activity or Fragment when the code inside runOnUiThread() runs what will cause Exceptions (I know using LiveData and MVVM pattern would solve this last problem but I am working in a legacy project and I can't refactor all the code so I am working with the clasical Activity mvc pattern)
So, there is another way of doing this? Could you give an example? I really searched a lot but didn't find anything...
Coroutines
I am actually working in a legacy project and I must use Java so can't use Kotlin coroutines, but I find them easy to use and so powerfull.
Any help would be appreciated!
Background
In Android, when an application is launched, the system creates a thread of execution for the application, called main thread (also known as the UI thread). Google introduces the main thread and its responsible as below.
The main thread has a very simple design: Its only job is to take and
execute blocks of work from a thread-safe work queue until its app is
terminated. The framework generates some of these blocks of work from
a variety of places. These places include callbacks associated with
lifecycle information, user events such as input, or events coming
from other apps and processes. In addition, app can explicitly enqueue
blocks on their own, without using the framework.
Nearly any block of code your app executes is tied to an event
callback, such as input, layout inflation, or draw. When something
triggers an event, the thread where the event happened pushes the
event out of itself, and into the main thread’s message queue. The
main thread can then service the event.
While an animation or screen update is occurring, the system tries to
execute a block of work (which is responsible for drawing the screen)
every 16ms or so, in order to render smoothly at 60 frames per second.
For the system to reach this goal, the UI/View hierarchy must update
on the main thread. However, when the main thread’s messaging queue
contains tasks that are either too numerous or too long for the main
thread to complete the update fast enough, the app should move this
work to a worker thread. If the main thread cannot finish executing
blocks of work within 16ms, the user may observe hitching, lagging, or
a lack of UI responsiveness to input. If the main thread blocks for
approximately five seconds, the system displays the Application Not
Responding (ANR) dialog, allowing the user to close the app directly.
To update a View, you must do it on the main thread, if you try to update in a background thread, the system will throw CalledFromWrongThreadException.
How to update a View on the main thread from a background thread?
The main thread has a Looper and a MessageQueue assigned with it. To update a View, we need to create a task then put it to the MessageQueue. To do that Android provides
Handler API which allows us to send a task to the main thread's MessageQueue for executing later.
// Create a handler that associated with Looper of the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());
// Send a task to the MessageQueue of the main thread
mainHandler.post(new Runnable() {
#Override
public void run() {
// Code will be executed on the main thread
}
});
To help developers easy to communicate with the main thread from a background thread, Android offers several methods:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Under the hood, they use Handler API to do their jobs.
Back to your question
AsyncTask
This is a class that is designed to be a helper class around Thread and Handler. It's responsible for:
Create a thread or pool of thread to do a task in the background
Create a Handler that associated with the main thread to send a task to the main thread's MessageQueue.
It is deprecated from API level 30
ThreadPoolExecutor
Create and handle a thread in Java is sometimes hard and might lead to a lot of bugs if developers do not handle it correctly. Java offers the ThreadPoolExecutor to create and manage threads more efficiently.
This API does not provide any method to update the UI.
Kotlin Coroutines
Coroutines is a solution for asynchronous programming on Android to simplify code that executes asynchronously. But it only available for Kotlin.
So my question is, what is the correct way of communicate the result
of background thread when this finish?.
1. Using Handler or mechanism built on Handler
1.1. If a thread is bounded with Activity/Fragment:
Activity.runOnUiThread(Runnable)
1.2. If a thread has a reference to a view, such as Adapter class.
View.post(Runnable)
View.postDelayed(Runnable, long)
1.3. If a thread does not bound to any UI element, then create a Handler on your own.
Handler mainHandler = new Handler(Looper.getMainLooper);
Note: A benefit of using Handler is you can use it to do 2 ways communication between threads. It means from a background thread you can send a task to the main thread's MessageQueue and from the main thread, you can send a task to the background's MessageQueue.
2. Using BroadcastReceiver
This API is designed to allow Android apps can send and receive broadcast messages from the Android system, other apps or components (Activity, Service, etc) inside the app, similar to publish-subscribe design partern.
Because of the BroadcastReceiver.onReceive(Context, Intent) method is called within the main thread by default. So you can use it to update the UI on the main thread. For example.
Send data from a background thread.
// Send result from a background thread to the main thread
Intent intent = new Intent("ACTION_UPDATE_TEXT_VIEW");
intent.putExtra("text", "This is a test from a background thread");
getApplicationContext().sendBroadcast(intent);
Receive data from activity/fragment
// Create a broadcast to receive message from the background thread
private BroadcastReceiver updateTextViewReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String text = intent.getStringExtra("text");
myTextView.setText(text);
}
};
#Override
protected void onStart() {
super.onStart();
// Start receiving the message
registerReceiver(updateTextViewReceiver, new IntentFilter("ACTION_UPDATE_TEXT_VIEW"));
}
#Override
protected void onStop() {
// Stop receving the message
unregisterReceiver(updateTextViewReceiver);
super.onStop();
}
This method is usually used to communicate between Android apps or Android apps with the system. Actually, you can use it to communicate between components in Android app, such as (Activity, Fragment, Service, Thread, etc.), but it requires a lot of code.
If you want a similar solution but less code, easy to use, then you can use the following method.
3. Using EventBus
EventBus is a publish/subscribe event bus for Android and Java. If you want to execute a method that runs on the main thread, just mark it with #Subscribe(threadMode = ThreadMode.MAIN) annotation.
// Step 1. Define events
public class UpdateViewEvent {
private String text;
public UpdateViewEvent(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
// Step 2. Prepare subscriber, usually inside activity/fragment
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
myTextView.setText = event.getText();
};
// Step 3. Register subscriber
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
// Step 4. Unregister subscriber
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
// Step 5. Post events from a background thread
UpdateViewEvent event = new UpdateViewEvent("new name");
EventBus.getDefault().post(event);
This is useful when you want to update a View when the activity/fragment is visible to users (they are interacting with your app).
Since the very beginning (API 1) the android way of communication between threads has been Handler. Actually AsyncTask is just a wrapper around a thread pool and it uses Handler also to communicate to the main thread, you can check out the source code and create you own wrapper similarly.
Handler is the very low-level primitive and I wouldn't say using Handler is ugly, but it definitely requires some knowledge of multithreading programming and makes the code more verbose. As you also mentioned there are a lot of issues arises, like your UI can be gone by the time the task is completed and you have to handle this on your side. That's always the case with the low-level primitives.
As you are looking for reputable sources, here is the official documentation on exactly this problem - communicating a result from background thread to the main thread in plain java.
So unfortunately there is no other - better and officially recommended - way of doing that. Of course there are plenty of java libraries like rxJava that are build on top of the same primitives but provides higher level abstractions.
I personally use AsyncTask like this:
Setup a broadcastReceiver in my Activity or Fragment
Call the asyncTask with any needed arguments in an Object[] using the Executor of your choice.
Once the AsyncTask has completed I Bundle with the data or result, send a LocalBroadcast containing this bundle.
In my Fragment or activity receive the broadcast and handle the result.
I have never had any issues with this method, I do understand some people are shying away from AsyncTask, but for most purposes and all I have come across this is a simple and reliable method.

Post a Runnable to another thread in plain java

In Android we have Handler#post(Runnable) method to post some code to the main thread from another
Is it possible to make same thing in plain java (for instance while using swing)?
Explaining the question:
Assume we have two threads: ThreadA and ThreadB. Both are started already and running side-by-side. And ThreadB wants ThreadA to invoke some method (again, ThreadA is already running).
Addition optional question (you may not answer it):
And if it's possible, someone explain me how does exactly Handler do in Android. How it's able to post some code to MainThread? What is a purpose of the Looper?
Addressing your additional question:
You said "In Android we have Handler#post(Runnable) method to post some code to the main thread from another"
It is not exactly correct. You can 'post some code' from any thread A to any thread B provided that thread B is initialized as a Looper and the thread A has a reference to a Handler for the target thread B.
It is very convenient when you need to do something on the UI thread because the UI thread already has a Looper and you can retrieve it from nearly everywhere. The static method Looper.getMainLooper is a way to get a Looper for the main thread. If you initialize a Handler with this Looper you can post a Runnable or send a Message to it (though if you post Runnable it also gets wrapped into a Message) and it will be executed on the UI thread.
Looper, as the name hints, is basically running a non-terminating loop for a thread. The Looper has an associated MessageQueue which it constantly checks for new Messages. Via the Handler initialized with a Looper you can enqueue Messages on this thread. The Messages are processed in a sequential order, depending on the when field of a Message.
Here's a basic implementation of a Looper thread:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
I suggest you read the Chapter 5 of Meike G.B. Android Concurrency. It will give you a comprehensive insight into the Looper/Handler framework. It is also great to browse the source code while you are reading, it is rather simple and self-explanatory.
Within Swing you would use
https://docs.oracle.com/javase/8/docs/api/javax/swing/SwingUtilities.html#invokeLater-java.lang.Runnable-
to run something on the main thread.
In general Java, an ExecutorService is like a thread pool and allows you to submit Runnable or Callable instances
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
However, if you aren't using an ExecutorService or Swing, there is no standard Java API to tell another thread to do something.

How to post callbacks in Android to any arbitrary thread

I am using the Unity game engine which also supports exporting to Android.
The engine uses multiple threads, including the UI thread and a separate scripting thread where all the user custom code is executing.
My scenario requires that i call some operation in a background thread, and i would like to marshal the result back to the main scripting thread.
I know the basics of the AsyncTask, Executor and Looper classes. Out of these, Looper seems like a good candidate since it allows setting up a queue and post back messages to a given thread (AsyncTask is "hardwired" to run the callback on the UI thread, which is not what i want here).
What is the proper way of achieving this?
There is 3 main ways to communicate with the UI thread :
Activity.runOnUiThread(Runnable)
View.post(Runnable)
Handlers
In your case, I advice you to create an Handler, as the 2 first solutions imply that you have a reference on your Activity or a View
Edit
If you want to use any thread in your app, just make sure a Looper has been set, and use an associated Handler
class YourLooperThread extends Thread
{
// make it accessible from the outside
private Handler handler;
#Override public void run()
{
Looper.prepare();
// Customize your handler, it has to be used in any thread which want to push a message in this thread's looper message Queue
handler = new Handler();
Looper.loop();
}
}
Be careful : all the other tasks you want to do in that thread must be done through the message queue, i.e posting a runnable in the handler. More information here : Handlers, MessageQueue, Looper, do they all run on the UI thread?

AsyncTask, Handler, Thread... Which one to choose [duplicate]

This question already has answers here:
Handler vs AsyncTask vs Thread [closed]
(13 answers)
Closed 8 years ago.
I know this Question has been asked many times but all answers I got wasn't clear for Me.
I want to implement a File deletion process. I discovered that to do this kind of work it's recommended to run all the process in a separated thread.
For that, I can use AsyncTask, Handler and Thread. AsyncTask seems to be a good solution. However, AsyncTask is designed for small task. (When i try to delete a file whose length is more than 1G, AsyncTask crashes or doesn't execute onPostExecute.
Others thread handlers (Thread, Runnable...) can't manage UI (Update UI or show progress).
My Question is What is the good thread handler for Long tasks and How to manage UI with it.
First of all, if you need to perform work outside your main thread, but only while the user is interacting with your app, then you should create a new thread, otherwise use a Service.
Now, everything you can do with AsyncTask, you can also do it with a Thread(+ Handler). But the AsyncTask makes the developer job easier, because it is designed to communicate a worker thread with the main thread(caller thread). Now, if you use a Hanlder you can also communicate a worker thread with a caller thread(Note that the caller thread is not necessarily the main thread, it could be communication between two worker threads), if the caller thread is the main thread, you better use AsyncTask.
As far as i know, it goes something like this:
Use AsyncTask if you need to run a short task communicating with the UI thread
Use a Thread and Handler to run longer tasks that requires communication between the worker thread and the main thread(caller thread)
Use Thread, Handler and Looper (or HandlerThread, which is class for starting a thread that already has a Looper) for longer tasks that require communication between the worker thread and the caller thread(not the main thread).
Use IntentService for longer task that does not requires user interaction and needs only one worker thread.
The best for me, is the Asynctask, because the structure is well defined, you can know when is running the thread and when show the result.
http://masl.cis.gvsu.edu/2010/04/05/android-code-sample-asynchronous-http-connections/
Good article on using handlers above.
To delete using handler:
Create a runnable that does three things:
Delete file
Obtain msg and send on success
Obtain msg and send on failure
Using some framework to manage threads or using concurrency package, post the runnable and it will do the file Del off main thread. Handler callback will be msg success or msg fail that will process on main thread wherview controller.
Check out Needle and you can forget Handlers and AsyncTasks. Needle is an open-source, simple but powerful multithreading library for Android. With it you can say things like:
Needle.onMainThread().execute(new Runnable() {
#Override
public void run() {
// e.g. change one of the views
}
});
or
Needle.onBackgroundThread().execute(new UiRelatedTask<Integer>() {
#Override
protected Integer doWork() {
int result = 1+2;
return result;
}
#Override
protected void thenDoUiRelatedWork(Integer result) {
mSomeTextView.setText("result: " + result);
}
});
very simple API
fixed thread pool size
customizable thread pool size
supports UI interaction ("do work and then use result on UI thread")
android 1.5+
behaves the same on all platform versions
Check it out on GitHub: https://github.com/ZsoltSafrany/needle

Anonymous class extending thread in Java

This is a Java syntax question, but just for some background.
Using android, I created a small app that went really slow and often crashed because when a button was clicked the onClick() method changed button images for various buttons. It was really clunky and slow and I found out after a search on the net that the problem is pretty common, and when changing lots of images in the onClick() method, its best to put them in a separate thread. And some kind person gave the code for doing this.
new Thread(new Runnable() {
public void run() {
quest.post(new Runnable() {
public void run() {
correct = nextQ();
}
});
}
}).start();
The nextQ() method and the "quest" TextView are mine. It's not really relevant to my question what they do, but nextQ does a database search and updates images, and running it outside the thread is really slow and crashy.
Now I copied and pasted this code into my code and it runs fine. A happy ending. But I dont feel comfortable using code I don't understand. And I don't know Java very well. SO I researched as best I could anonymous inner classes, but I'm still stumped by the code.
So the anonymous class extends thread, and as it's argument uses an anonymous class, implementing runnable, in which the "meat" of the code is placed..
Questions:
1)Why would I do this? I can understand using thread OR runnable, but why together?
2)How does this work? I went back to basics of thread and runnable, but I don't see how you use them together this way.
you are creating an anonymous implementation of the Runnable interface
you are passing that implementation to the constructor of the Thread class. So you are not extending Thread, you are just instantiating it, and pass an argument.
you then start() the thread. Thus the run() method of the passed argument will be invoked in a new thread.
You need to do this, because:
the Runnable defines what gets executed
the Thread actually executes it.
Your confusion is understandable, since a Thread is also Runnable. That's why in Java 5 the executors framework was introduces, which separated the execution mechanism (an executor) from the executed code (Runnable or Callable).
So the anonymous class extends thread,
No it does not. It implements Runnable.
1)Why would I do this? I can understand using thread OR runnable, but why together?
If you use Runnable, you still need to run it somehow, and one way to do that is to create a new Thread and give it to Runnable (which is what is being done here).
2)How does this work?
new Thread(runnable) creates a new Thread, which you can then start(). It will execute the code in the Runnable's run() method.
Runnable contains the code that should be executed (an alternative is Callable).
Thread controls how and when the code is executed (alternatives are ExecutorService or calling run() directly for synchronous execution on the current Thread)
In general (and to keep these two functions apart), you do not want to extend Thread, you only want to implement Runnable or Callable.
It is possible to extend Thread and directly implement run (rather than letting it delegate to the Runnable), but that is sort of old school. If they were to redesign the Java API today, Thread would probably not implement Runnable anymore. Thread is more of a Runner than it is a Runnable.

Categories

Resources