Usage of a handler - android

I'm recently getting involved in some concurrent programming specially with Java and Android.
I have some questions regarding Handlers.
1 - It is known that we need to associate a Handler with a thread, and it will run on the thread it was invoked on. However, in some examples on SO, the user is doing
public class MainActivity extends Activity
{
private Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState)
{
handler.postDelayed(runnable, 1000);
}
private Runnable runnable = new Runnable()
{
public void run()
{
//Do whatever
handler.postDelayed(this, 30000);
}
};
In this example, I assume we are doing the Handler thing on the UI Thread, RIGHT ?
Can I do a network operation here in place of //DO Whatever ? I don't think so, because we are on the main thread.
Is doing this pointless ? As one may use AsyncTask to replace this task ?
How can I apply this same example but not on the UI thread, rather a seperate thread ?
Do thread or Runnables have something similar to post delayed ?
Is it common to use the handler just for its postdelayed feature and not the main task handlers are made for, ie, being the middle man between the thread and the UI/Activity ?

Handlers are useful only when you want update UI. As you may know we cannot update UI from non UI Thread. If you are going to do some network stuff in background thread, and then update UI, you have to use Handler class or AsyncTask or you can do like this:
(from non UI Thread)
SomeView.post(new Runnable() {
//updating UI
});

If whatever you are doing is "heavy" you should be doing it in a Thread. If you do not explicitly start it in its own thread, then it will run on the main (UI) thread which may be noticeable as jittery or slow to respond interface by your users.
Interestingly when you are using a thread it is often useful to also use a Handler as a means of communication between the work thread that you are starting and the main thread.
A typical Thread/Handler interaction might look something like this:
Handler h = new Handler(){
#Override
public void handleMessage(Message msg){
if(msg.what == 0){
updateUI();
}else{
showErrorDialog();
}
}};
Thread t = new Thread() {
#Override
public void run(){
doSomeWork();
if(succeed){
//we can't update the UI from here so we'll signal our handler and it will do it for us.
h.sendEmptyMessage(0);
}else{
h.sendEmptyMessage(1);
}
} };
In general though, the take home is that you should use a Thread any time you are doing some work that could be long running or very intensive (i.e. anything network, file IO, heavy arithmatic, etc).

Related

What are Handlers and Runnables for in Android?

Please I am blocked with this concept of Handlers and Runnables in Android. Can someone please give me detailed explanation on Handlers and Runnables? Their syntax and implementation? I have read many articles on this but the concepts are not still clear and are even deployed in Java. Thanks in advance
I'm going to try to simplify so bear with me if it is not 100% accurate.
Basically, a Handler is used to communicate with a MessageQueue associated with a Thread.
If you're on the main thread, or if you've called Looper.prepare() in the Thread that you're in, it has a Looper which is basically a holder for the MessageQueue.
This queue is constantly polled so that whenever a Message goes into it, it's dealt with on the Thread associated with this MessageQueue
If you're trying to execute a piece of code on a particular Thread, you have to use a Runnable. It is just an interface that has a void run() method which will be executed by the Looper, on its Thread.
Let's say you're doing a network request, you want it to happen on another Thread but when you get the result you somehow need to pass the data back to the Main Thread in order to update your UI because Views can't be modified from another Thread.
You would do it like so:
// This will let you run method on main thread (even if you're not on main thread)
private final Handler handler = new Handler(Looper.getMainLooper());
// This will let you run method on background thread
private final Executor executor = Executors.newSingleThreadExecutor();
public void doSomething() {
// posting to executor will go to background thread
executor.post(new Runnable() {
#Override
public void run() {
// This will now run on background thread
// you can for example do network request here
// posting to handler will go back to main thread
handler.post(new Runnable() {
#Override
public void run() {
// This will execute on the Main Thread
}
});
}
});
}

When to use handler.post() & when to new Thread()

I'm wondering when should I use handler.post(runnable); and when should I use
new Thread(runnable).start();
It is mentioned in developers documentation for Handler:
Causes the Runnable r to be added to the message queue. The runnable
will be run on the thread to which this handler is attached.
Does this mean if I write in the onCreate() of Activity class:
Handler handler = new Handler();
handler.post(runnable);
then runnable will be called in a separate thread or in the Activity's thread?
You should use Handler.post() whenever you want to do operations on the UI thread.
So let's say you want to change a TextView's text in the callback. Because the callback is not running on the UI thread, you should use Handler.post().
In Android, as in many other UI frameworks, UI elements (widgets) can be only modified from UI thread.
Also note that the terms "UI thread" and "main thread" are often used interchangeably.
Edit: an example of the long-running task:
mHandler = new Handler();
new Thread(new Runnable() {
#Override
public void run () {
// Perform long-running task here
// (like audio buffering).
// You may want to update a progress
// bar every second, so use a handler:
mHandler.post(new Runnable() {
#Override
public void run () {
// make operation on the UI - for example
// on a progress bar.
}
});
}
}).start();
Of course, if the task you want to perform is really long and there is a risk that user might switch to some another app in the meantime, you should consider using a Service.
To answer you specific question:
Does this mean if in the onCreate of Activity class I write:
Handler handler = new Handler() hanlder.post(runnable); then, runnable
will be called in a separate thread or on the Activity's thread?
No it won't be. The Runnable will be called on the Main Thread itself.
Handler is simply used for posting a message to the thread to which it is attached (where its is created).
It does not create a thread on its own.
In your example, you created a Handler in the main Thread (that where Activity.OnCreate() is called) and hence any message posted on such a Handler will be run on the Main Thread only.
Example is jacked:
mHandler = new Handler();
new Thread(new Runnable(){
#Override
public void run () {
mHandler.post(new Runnable() {
#Override
public void run () {
mUiView.setX(x);
}
});
}
}).start();
Alternatively you can skip the handler and use the post method on the view directly:
new Thread(new Runnable(){
#Override
public void run () {
mUiView.post(new Runnable() {
#Override
public void run () {
mUiView.setX(x);
}
});
}
}).start();
This is a good post that outlines the difference: What exactly does the post method do?
use handler.post() when you want to post the code (usually from background thread) to the main thread. Yea, POST,just like you, post a letter to someone. With the help of handler the code will be executed ASAP i.e. almost immediately.

Android Inception (A thread within a thread)

I have one function which queries a network server with a few "ping pongs" back and forth, and have written a custom handler to handle the message communication between my main UI thread and the communication thread (I was using AsyncTask for this, but as the program got more complex, I have decided to remove the communication code to its own class outside of the main activity).
Triggering a single instance of this thread communication from onCreate works perfectly, no problem.
I want this query to run on a regular timed basis -- in the background -- for the entire time the app is in use, so I've set up another thread called pollTimer, which I'm trying to use to call the OTHER thread at a regularly scheduled basis.
Obviously, it's crashing, or I wouldn't be posting this.
Is there a way to get a thread within a thread? Or put differently, trigger a thread from another thread?
Timer pollTimer = new Timer();
private void startPollTimer(){
pollTimer.scheduleAtFixedRate(new TimerTask(){
public void run(){
Log.d(TAG,"timer dinged");
//if the following is commented out, this "dings" every 6 seconds.
//if its not commented out, it crashes
threadedPoll();
}
}, 3120, 6000);
}
private void threadedPoll() {
testThread(asciiQueries,WorkerThreadRunnable.typeLogin);
}
edit: it would probably help to include the "testThread" function, which works by itself when called from onCreate, but does not make it when called from the Timer.
"WorkerThreadRunnable" is the massive chunk of code in its own class that has replaced the mess of having AsyncTask handle it inside the main activity.
private Handler runStatHandler = null;
Thread workerThread = null;
private void testThread(String[] threadCommands, int commandType){
if(runStatHandler == null){
runStatHandler = new ReportStatusHandler(this);
if(commandType == WorkerThreadRunnable.typeLogin){
workerThread = new Thread(new WorkerThreadRunnable(runStatHandler,threadCommands, WorkerThreadRunnable.typeLogin));
}
workerThread.start();
return;
}
//thread is already there
if(workerThread.getState() != Thread.State.TERMINATED){
Log.d(TAG,"thread is new or alive, but not terminated");
}else{
Log.d(TAG, "thread is likely deaad, starting now");
//there's no way to resurrect a dead thread
workerThread = new Thread(new WorkerThreadRunnable(runStatHandler));
workerThread.start();
}
}
You seem to be well on the way already - the nice thing about handlers, though, is that they aren't limited to the UI thread - so if you have a Handler declared by one thread, you can set it up to take asynchronous instructions from another thread
mWorkerThread = new WorkerThread()
private class WorkerThread extends Thread {
private Handler mHandler;
#Override
public void run() {
mHandler = new Handler(); // we do this here to ensure that
// the handler runs on this thread
}
public void doStuff() {
mHandler.post(new Runnable() {
#Override
public void run() {
// do stuff asynchronously
}
}
}
}
Hopefully that helps... if I'm totally off base on your problem let me know
Wots wrong with a sleep() loop? Why do you have pagefuls of complex, dodgy code when you could just loop in one thread?

What's the android preferable way of spawning a new thread?

Coming from the basic Java world I know there's a way to spawn a thread by creating a new Runnable and passing it to a new Thread and calling start on it. Something like:
Runnable r = new Runnable() {
#Override
public void run(){
}
}
new Thread( r ).start()
Now joining the Android world it seems the Android eco system provides a few other ways to spawn a thread. One of them is Activity.runOnUiThread (for having stuff done on the UI) and Handler.post( runnable ).
What I am wondering about is what's the Android preferable way of spawning a new thread. I do see a lot cases such as:
Handler handler = new Handler()
handler.post( r )
Is there a good reason to use Handler to spawn a thread as opposed to creating a new Thread old way?
Thanks.
Yev
Check out the AysncTask framework. It seems like that's how Google wants you to handle threads...although you can use standard java threading.
The Handler in the way you've demonstrated doesn't actually spawn a new thread. Handlers are not threads, but are rather a means of IPC to let one thread tell another thread to run code. You still spawn off threads in the same old way, but the Handler helps those threads communicate better.
Say, for example, you have a Thread that you've spawned off in the background in the usual way:
Runnable r = new Runnable() {
#Override
public void run(){
}
}
new Thread( r ).start()
It runs in the background doing processing, but it needs to update the UI with it's progress, so it calls back to the Activity:
onProgress(int progress) {
// update UI
}
If you run that code as is, it will throw an exception, because only the UI thread is allowed to update the UI. Handlers can solve that problem like so:
public void onProgress(int results) {
mHandler.post(new UIUpdater(results));
}
private class UIUpdater implements Runnable {
UIUpdater(int results) {
//construct whatever...
}
#Override
public void run() {
//Update UI
}
}
Alternately, you can have Android manage Threads and Handlers for you through the AsyncTask framework
Handler is not supposed to spawn thread , but to post new task to UI thread. IMO the way to spawn thread is the java way, through runnable or extended thread directly. The android guys wrapped an Executor around the Async task and exposed some method that run directly in UI thread, and one to run your task in background.

Specifics on using Looper.prepare() in Android

I'm having a bit of trouble understanding how to use the Looper prepare()/loop()/quit() logic.
I have three threads: one is the UI thread, one is a game logic thread and the last is a network communication thread (a background thread, lives only while being used).
The game thread has many dependencies on the results of the network calls, so I wanted to spin the network thread off of the game thread and have a Handler post the result back.
Of course, since the UI thread is not involved I need to call Looper.prepare()... somewhere. I thought it should be called in the game thread, but I can't do that because loop() takes it over.
How do I go about posting back to the game thread from network thread with my handler?
What's going on is that once you call Looper.prepare() followed by Looper.loop() on a Thread, all that Thread will ever do is service its MessageQueue until someone calls quit() on its Looper.
The other thing to realize is that, by default, when a Handler is instantiated, it's code will always execute on the Thread it was created on
What you should do is create a new Thread and in run() call Looper.prepare(), setup any Handlers, and then call Looper.loop().
Bearing these things in mind here is the basic pattern I use a lot of places. Also, there's a good chance you should just be using AsyncTask instead.
public class NetworkThread extends Thread {
private Handler mHandler;
private Handler mCallback;
private int QUIT = 0;
private int DOWNLOAD_FILE = 1;
public NetworkThread(Handler onDownloaded) {
mCallback = onDownloaded;
}
public void run() {
Looper.prepare();
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
// things that this thread should do
case QUIT:
Looper.myLooper().quit();
break;
case DOWNLOAD_FILE:
// download the file
mCallback.sendMessage(/*result is ready*/);
}
}
}
Looper.loop();
}
public void stopWorking() {
// construct message to send to mHandler that causes it to call
// Looper.myLooper().quit
}
public void downloadFile(String url) {
// construct a message to send to mHandler that will cause it to
// download the file
}
}
Could you tell some examples for what you are using your network thread? I think you can solve your problems without using Looper.
You can use ASyncTask to perform background task that may update some values in your UI thread. If user has to wait until background operation will be finished, you can show ProgressDialog and block application in OnPreExecute method, and then hide it in onPostExecute.
As I said, please describe more your needs and target which you want to achieve.

Categories

Resources