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.
Related
I have some code which uses single HandlerThread with Handler to send messages to it. Is there any way to do this with coroutines? I don't want to create new coroutine every time, I just want to execute blocks of code on the HandlerThread. Please help
If you are looking to execute a block of code in the main Android thread, then you can use UI context from kotlinx-coroutines-android module like this:
launch(UI) {
... // this block of code will be executed in main thread
}
The above snippet sends a message to the main handler to execute your code.
If you looking for a custom handler thread for background work, then you can create a single-threaded context in one of two ways.
Generic approach: Use newSingleThreadedContext() like this:
val ctx = newSingleThreadedContext() // define your context
launch(ctx) { ... } // use it to submit your code there
Android-specific approach: Create new Android Handler, use Handler.asCoroutineDispatcher() extension to convert it to the coroutines context extension. Then you'll be able to use launch to send your blocks of code for execution.
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.
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.
I sent "Scores Activity" to doinbackground then run a function on Scores Activity but getting
"Only the original thread that created a view hierarchy can touch its views." on "birinci.setText(txt);" line.
what am I missing here looks using same context?
Scores Activity
{
Object[] stuff = {this.dhn, Scores.this};
ConnectXML runXML = new ConnectXML();
runXML.execute(stuff);
}
public void setScoreListUpdate(String txt)
{
birinci.setText(txt);
}
private Scores myScores;
protected String doInBackground(Object... arguments) {
myScores = (Scores)stuff[1];
myScores.setScoreListUpdate(result);
}
The error message already gives the answer: you can't touch (edit/modify/update/etc.) any views from a thread that did not create them. Since anything that is executed in the doInBackgrund(...) of an AsyncTask is done by a separate thread, you can't do any direct view manipulations in there.
The solution is quite simple: override the other methods an AsyncTask provides, depending on your needs. If you're trying to update a view after all work is done, simply override onPostExecute(...). If you want to indicate some sort of progress while the work is being done in the background, use onProgressUpdate(...). Everything in there is being executed by the main UI thread (which created all views).
Please have read through the documentation on AsyncTask, since that describes the different steps and possibilities quite clearly.
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<>.