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.
Related
I am making an android game which is made up of a game loop that is constantly running as well as use of the android UI stuff. So they need to be in separate threads to work concurrently.
I am planning to put the game loop inside an AsyncTask however it says in the developer.android documentation that
AsyncTasks should ideally be used for short operations (a few seconds at the most.)
My game loop will in theory be operating indefinitely and almost always for more than a few seconds. Is the asynctask the right place to put this then or is there another preferred method to split up a game loop and the UI operations
AsyncTasks are for short operations only, as the documentation has stated. Also, they usually do some work that shouldn't interfere with the UI. Hence, "Async" and "Task".
What you should use instead is a new Thread. This is called Multi-Threading. There are a lot of Game Frameworks out there which will have problems with android's UI. Though you have not stated what UI Operations you are talking about, but if you plan to use the android's widgets(UI), you could call Activity.runOnUiThread() to run a code on the UI Thread, for example, changing a TextView's text.
Here is a snippet on how you would create a never ending loop in a new thread(or something like this, i dont remember if the function is private):
new Thread(new Runnable() {
#Override
private void run() {
while(true) {
//your code goes here
}
}
});
Although AsyncTask allows you to perform background operations and publish results on the UI thread without having to manipulate threads, it should ideally be used for short operations (a few seconds at the most).
To keep things simple, you could use a Handler, or even better, research about the various APIs provided by the java.util.concurrent package.
import android.os.Handler;
// Create the Handler
private Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnable = new Runnable() {
#Override
public void run() {
// Insert simulation processing code here
// Repeat 60 times per second
handler.postDelayed(this, 1000 / 60);
}
};
// Start the Runnable immediately
handler.post(runnable);
Remember that multi-threading is the easy part. Correct synchronization is hard.
When I run replication on Couchbase Lite in Android from UI Thread, it happens that the replication executes in another thread and notifications (Via addChangeListener() method) are received in a third Thread. My code for Pull Replication is as follow:
Replication pullRep = getDatabase().createPullReplication(syncUrl);
pullRep.setContinuous(true);
pullRep.addChangeListener(this);
pullRep.start();
My question is: How can I run synchronous replication or at least get notifications on the same Thread from which replication was started ?
My opinion is that replication must occur in the current thread. The developer must handle thread issues.
I´m very new with Couchbase Lite and maybe I´m wrong.
I apologize if I'm misunderstanding your situation, but I believe what you're trying to say is you can't update the UI with changes discovered in the Couchbase listener because the listener operates on a background thread and not the UI thread. Am I correct?
You definitely don't want to run potentially long tasks on the UI thread because it will create a poor UX. Asynchronous is the way to go.
You might try something like this instead:
Handler threadHandler = new Handler();
couchbaseDatabase.addChangeListener(new Database.ChangeListener() {
public void changed(Database.ChangeEvent event) {
// Alter variables related to the UI (maybe an array for a list view)
threadHandler.post(updateUI);
}
});
final Runnable updateUI = new Runnable() {
public void run() {
// Refresh the UI
adapter.notifyDataSetChanged();
}
};
Of course what I pasted is just bits and pieces and not a true working example. My point here is that I used a Handler. There are a ton of other ways that will work as well.
Would this work for you?
Best,
Hi I'm having trouble setting up a thread to run some code that requires a thread with a looper. The task will take a while and it can't be on the main thread. I've done a lot of Google searching but I can't seem to get this to work. Any help is appreciated. Thank you.
private HandlerThread handlerThread = new HandlerThread("My HandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
#Override
public void run() {
checkIfWeAreOnMain();
}
});
void checkIfWeAreOnMain() {
if(Looper.getMainLooper().getThread() == Thread.currentThread()){
//I'm getting true here
}
}
A Handler will always run on the thread you're starting it from. It was designed to do that.
If you need something to be run on the background with some really nice and easy callbacks, use an AsyncTask.
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 package such as Executor, ThreadPoolExecutor and FutureTask.
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've been reading up on how to use Thread in java, and I'm hoping someone can help me verify I'm using it correctly. I'm concerned that I should be calling .interrupt() or destroying the thread in some way.
I have a simple script that just hits my server to verify some data. My code:
Thread checkregister = new Thread(){
#Override
public void run(){
checkSystem();
}
};
checkregister.start();
Where checkSystem() posts the device id to a php script and waits for the response via HttpClient & HttpResponse. There isn't any looping so I don't think blocking is called for, but please let me know if I'm wrong.
No need to destroy the Thread. The Thread is effectively taken out of the thread scheduler as soon as run() returns.
If for some reason you need a way to prematurely "end" the Thread, this is a bit more complicated and there's been a lot of discussion about the proper way to do it. Simple way though is to just call stop() on the Thread.