To update the GUI from other threads, there are basically two main approaches:
Use java.lang.Runnable with any of these methods:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Handler.post(Runnable)
Use android.os.Message:
Handler.sendMessage(Message) / Handler.handleMessage(Message)
You can also use AsyncTask, but my question is more focused on the use case of updating a very simple component. Let's see how it would be done using both approaches:
Using Runnables:
TextViev tv = ...;
final String data = "hello";
Runnable r = new Runnable() {
#Override
public void run(){
tv.setText(data);
}
};
//Now call Activity.runOnUiThread(r) or handler.post(r), ...
Using messages:
Message m = handler.obtainMessage(UPDATE_TEXT_VIEW, "hello");
handler.sendMessage(m);
//Now on handler implementation:
#Override
public void handleMessage(Message msg) {
if(msg.what == UPDATE_TEXT_VIEW){
String s = (String) msg.obj;
tv.setText(data);
} ... //other IFs?
}
IMHO, Messages are not the way to go because:
Not easy to understand for new non-android programmers (handler hooks to its thread during construction).
Object payload should be Parcellable if the message crosses process boundaries.
Messages are reused (error prone if not properly cleaned up?)
The handler has a dual role (it sends messages, but also handles them)
Message attributes are public, but also offer getter/setter.
On the other hand, Runnables follow the well known command pattern, and are more programmer-friendly and readable.
So what are the advantages of using Messages over Runnables? Are Messages pushed into the background in modern day Android programming? Is there anything you can do with Messages that can't be done with Runnables?
Thanks in advance.
I would say there is little difference between using a Message vs a Runnable. It'll mostly boil down to personal preference. Why? Looking at the source code you'll find that posting a Runnable uses the same exact messaging mechanism. It simply attaches the Runnable to a Message and sends that.
4.4.2 Source Code
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
Ref: Grep Code - Handler
Messages can be reused, so it results in fewer objects created and less GC. You also end up with fewer classes and anonymous types.
One big advantage is that a class sending a Message to a Handler doesn't need to know anything about the implementation of that Message. That can aid in encapsulation depending on where it's used.
Lastly consider the difference in cleanliness between
mHandler.obtainMessage(DO_STUFF, foo).sendToTarget();
vs
final Foo tempFoo = foo;
mHandler.post(new Runnable(){
#Override
public void run(){
doStuff(tempFoo);
}
};
If you have several places where you would have to doStuff(), the former is MUCH more readable and you'll have less code duplication.
Handler interface provides much more functionality than runOnUiThread(), according to docs:
There are two main uses for a Handler:
(1) to schedule messages and runnables to be executed as some point in the future
(2) to enqueue an action to be performed on a different thread than your own.
runOnUiThread does only a subset of (2). ie "enqueue an action to be performed on UI thread"
So IMO unless you need those extra features runOnUiThread is sufficient and preferred way.
I prefer Runnable to Message. I think code using Runnable is much clearer than Message, because the event handling code is very close to the event. Also, You can avoid the overhead of defining constants and switch cases.
And I don't think using Runnable violates encapsulation. You can extract the code in Runnable.run() into another method in the outer class, for example on...Event(), or even wrap it into an EventHandler object. Both ways are much clearer than using Message, especially when you need store references in Message, because using Runnable avoids downcasting msg.obj. And the nameless field msg.obj is also error prone and sometimes inefficient to understand.
And Runnable can also be reused by storing it as a field.
Related
I was learning about Looper and Handler and most time I read about it that it use to Communicate with UI thread. But then I saw the code which was child class of Handler with handleMessage(msg : Message) method then I got confused, because we can interact with GUI thread without extending Handler class.
As example in kotlin android.
val handler = Handler();
handler.post({
// update GUI here
});
So I can easily interact with GUI thread without implementing child class or handleMessage().
Let me explain little more about my quesiton. Sometime I see this example.
class HandlerSub : Handler(){
override fun handleMessage(msg : Message){
// update GUI here.
}
}
val handler = HandlerSub();
handler.send({
// send something..
});
So in the above example both code are being used for updating/interacting with GUI thread. but the 1st code is more simple easy and less code to interact with GUI.
Then what is real purpose of handleMessage() method and when we should implement it?
The sendMessage(...) call is used when you want message.obj to be some custom class, to send it to potentially another thread for processing. This is normally done by having message.what be an ID, and knowing the object type for that particular id's message.obj, then casting to that object type. This is used in many places throughout the Android framework, for example check the BluetoothStateMachine and how they handle processMessage(Message msg) in each one of their state classes. Each one of these states is delegated to by Handler.
I love the convenience of the Handler class; I can easily queue messages and even delay messages. However, all the code runs on the UI thread which is causing stuttering of the animation.
Is there a class, like Handler, that doesn't run on the UI thread ?
You could always use a HandlerThread. I do not have a simple example of this handy, unfortunately.
Personally, I tend to use java.util.concurrent classes directly for things that do not involve the main application thread (e.g., LinkedBlockingQueue, ExecutorService).
I'm a little confused by the currently accepted answer which seems to imply that using Handler on a non-UI thread isn't possible, because it's something I've done quite routinely and I thought it was pretty well known.
Within a non-UI Thread:
#Override
public void run() {
Looper.prepare();
...
mThreadHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
...
break;
default:
break;
}
}
};
Looper.loop();
}
Using the mThreadHandler, messages can be sent to be processed by the Handler in the above non-UI Thread.
If there are any good reasons for not using the Handler / Message classes to post work to be done on a non-UI Thread in this way then I'd like to know. It has been working fine for me so far though. The only reason I've read for not using a Handler in this way is that "a Handler is meant for posting stuff to the UI thread" which is not in itself a good technical basis.
1.
I have main UI thread and it uses library functions.
MainUI {
library.funcA(1);
library.funcB(2,3);
}
I don't want Main-Thread to wait for the end of each call. Also creating new thread for each call is ineffective and not thread-safe so I want them to run on another same thread.
So I created another thread with a single message queue / handler.
MainUI {
handler.post(new Message(FUNC_A,[1]));
handler.post(new Message(FUNC_B,[2,3]));
}
but it seems having overhead that I need to create new Message object every time and decode it again in handleMessage(). Furthermore It looks ugly to handle the various number of arguments packing/unpacking. I thought making all functions as Runnable and post them to handler, but functions have different arguments and I need to make new classes extending Runnable class!
my current plan is to insert synchronized keywords into every function in library so threads run one by one,
but I dislike many threads creating/disappering so making system heavy (also not thread-safe). I want to hear opinions.
2.
if the library is called from many threads (not only Main-thread), what's the best way to convert calls to run on the library's own single thread?
In my opinion, your current approach is feasible option to make thread-safe. However, if you want to go for having Runnable passed to handler, you could consider overloading your Runnable class. Here is pseudo-code
private Class MyRunner extends Runnable{
public MyRunner(){
//This is without any argument
}
public MyRunner(arg1){
//This is with 1 argument
}
public MyRunner(arg1,arg2){
//This is with 2 arguments
}
}
Still, you will have many instances of MyRunner class created.
You can use a Runnable like this:
int x = 1;
int y = 2;
// "a" and "b" are here to show how variable values can be sent to funcB.
// You could skip this and just have "funcB( 1, 2 )", of course.
final int a = x;
final int b = y;
handler.post( new Runnable() {
public void run() { library.funcB( a, b ); }
} );
The handler bit is a bit trickier. It has to run a looping thread to run each Runnable from the queue. Then it has to have a post method to put things on the queue. Some form of blocking queue would be the simplest way to link the two, saving you from having to do your own Object.wait/Object.notify. Synchronizing the post method would be the easiest way to keep multiple threads from tripping over each other.
I have a client software (on Android) that listens to incoming messages. The messages are received in a while loop that waits for messages to come. When a message is found, it updates the GUI. [Since in Android, GUI can not be updated directly ] A thread is called to do this. My problem is, if there are many messages, results in many threads! And it creates a clumsy situation. My abstract code is,
My_Client()
{
send_text_function() // My question is not about it
in_a_thread_Call_receive_from_others_function() [see 1]
}
receiving_funtion() // [this function is mentioned above as (see 1), called in a thread]
{
while( waiting for new message)
{
>>A new message found >> create a thread to update the GUI. // << Here is my question. see 2
//android.os.Handler.thread type thread!
}
}
label 2: Now this thread is created each time there is a message. How can I just create one thread and keep using it again and again? Any idea?
Create a new Thread.
In the run() method of the Thread create a new Handler.
When you want to do something on the target thread, use the Handler's post() method.
You can create a Handler on the Main thread to post-back operations that update the GUI.
Also consider using AsyncTask<>.
Currently I'm using the following construction:
while(continue)
{
if(somethingChanged)
{
draw();
}
}
Is this way of waiting efficient, or is there a better way to do this?
--
As requested, more info:
I'm drawing on a SurfaceView, with a Thread locking the Canvas and calling the onDraw(Canvas) method. When the thing I have drawn hasn't changed, I don't need to call the onDraw(Canvas) method, so I keep a boolean somethingChanged.
Also, when I touch the screen, I draw let's say a circle at the point of touch, so when I'm touching the screen, somethingChanged is true.
You can also use a wait() and make the other threads notify() this one when something has changed (if the somethingChanged is changed by other threads).
You probably doing a game, I recommend that article: http://dewitters.koonsolo.com/gameloop.html There are very good possible solutions for your request.
Android has a better mechanism regarding idle loops than the std java approach.
It consists of a Looper and a Handler which do the work for you:
Handler myHandler;
...
public void run() {
Looper.prepare(); //this tells Android that your thread will contain a loop
myHandler = new Handler() {
public void handleMessage(Message msg) {
draw();
}
};
Looper.loop; //starts the loop
}
All you have to do to call the draw method is to send a message to that handler instead of setting the boolean var.
Message mess;
myHandler.sendMessage(mess)
That way you can also send any object in that message to the loop, too and android does the thread synchro and message queue stuff for you. And - most importantly - it is efficient, too.
If nothing changed, this is an endless loop that will very probably use 100% cpu, so I'd say that you should at least add some Thread.sleep() calls to give other threads a chance do to something (e.g. changing the value of somethingChanged)
Usually, in infinite loops, you should have some mechanism to avoid it to take over all time of the cpu. This is done, for example, with a sleep. Even a brief sleep will alleviate the use of the processor.
Assuming that this code is in an thread:
while(continue)
{
if(somethingChanged)
{
draw();
}
Thread.sleep( mySleepTime );
}