Why to use Handlers while runOnUiThread does the same? - android

I have come across both Handlers and runOnUiThread concepts. But to me it still seems to be a doubt as on which facts do they differ exactly.
They both are intended to do UI actions from a background thread. But what are the factors that are to be considered while we choose among the two methods.
For example consider a Runnable Thread which performs a web service in the background and now I want to update the UI.
What would be the best way to update my UI? Should I go for Handler or runOnUiThread?
I still know I could use a AsyncTask and make use of onPostExecute. But I just want to know the difference.

Activity.runOnUiThread() is a special case of more generic Handlers. With Handler you can create your own event query within your own thread. Using Handlers instantiated with the default constructor doesn't mean "code will run on UI thread" in general. By default, handlers are bound to the Thread from which they were instantiated from.
To create a Handler that is guaranteed to bind to the UI (main) thread, you should create a Handler object bound to Main Looper like this:
Handler mHandler = new Handler(Looper.getMainLooper());
Moreover, if you check the implementation of the runOnUiThread() method, it is using Handler to do the things:
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
As you can see from code snippet above, Runnable action will be executed immediately if runOnUiThread() is called from the UI thread. Otherwise, it will post it to the Handler, which will be executed at some point later.

Handlers were the old way (API Level 1) of doing stuff, and then AsycTask (API Level 3) were introduced, along with a stronger focus on using runOnUIThread (API Level 1). You should avoid using handlers as much as possible, and prefer the other two depending on your need.

Handler have many work like message passing and frequent UI update if you start A Thread for any running a task .A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue ,, which is very useful in many application like bluetooth chat ,, wifi chat ... and handler has as Method PostDelay and PostAtTime by which you can play around any view to animate and change visibility and so on
You must look in this
http://developer.android.com/guide/components/processes-and-threads.html
http://developer.android.com/tools/testing/activity_testing.html

Following HitOdessit's answer.
You can create a class like this.
public class Global{
private static Handler mHandler = new Handler(Looper.getMainLooper());
public static void runOnUiThread(Runnable action){
mHandler.post(action);
}
}
And then call it like this.
Global.runOnUiThread(new Runnable(){
//Your code
});
And this can be run from anywhere (where you have access to your Global class).

What would be the best way to update my UI? Should I go for Handler or runOnUiThread?
If your Runnable needs to update UI, post it on runOnUiThread.
But it's not always possible to post Runnable on UI Thread.
Think of scenario, where you want need to execute Network/IO operation Or invoke a web service. In this case, you can't post Runnable to UI Thread. It will throw android.os.NetworkOnMainThreadException
These type of Runnable should run on different thread like HandlerThread. After completing your operation, you can post result back to UI Thread by using Handler, which has been associated with UI Thread.
public void onClick(View view) {
// onClick on some UI control, perform Network or IO operation
/* Create HandlerThread to run Network or IO operations */
HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
/* Create a Handler for HandlerThread to post Runnable object */
Handler requestHandler = new Handler(handlerThread.getLooper());
/* Create one Handler on UI Thread to process message posted by different thread */
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler);
NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler);
requestHandler.post(r1);
requestHandler.post(r2);
}
class NetworkRunnable implements Runnable{
String url;
Handler uiHandler;
public NetworkRunnable(String url,Handler uiHandler){
this.url = url;
this.uiHandler=uiHandler;
}
public void run(){
try {
Log.d("Runnable", "Before IO call");
URL page = new URL(url);
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader buff = new BufferedReader(in);
String line;
while ((line = buff.readLine()) != null) {
text.append(line + "\n");
}
Log.d("Runnable", "After IO call:"+ text.toString());
Message msg = new Message();
msg.obj = text.toString();
/* Send result back to UI Thread Handler */
uiHandler.sendMessage(msg);
} catch (Exception err) {
err.printStackTrace();
}
}
}

Related

android send message to worker thread

I have a thread where I need to periodically perform some checks, get files from the web, and send messages to the main UI thread. I even need to use UI thread parameters (like the map visible area) on each loop of the worker thread. So I suppose that i need to implement bidirectional communication between UIthread and workerThread.
Another problem is that I need to save the identifier of each marker added to the map. I want to save the result of map.addMarker inside my custom array stored in my worker thread. this means that from the uithread, where i update the map, i should tell the workerThread to update the array of markers..
This is a sample of my actual worker thread:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
#Override
public void run(){
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
My actual problem is that when the UI thread ends processing the message received from the worker thread i should perform an action on the worker thread.
I thought 2 solutions:
1)wait on the worker thread till the message has been processed by the UI thread
2)process the message on the UI thread and then send a message to the worker thread.
I don't know how to do the solution1, so i tried the solution2. I tried adding a looper to my worker thread (RUN sub), this way:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
#Override
public void run(){
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// Act on the message received from my UI thread doing my stuff
}
};
Looper.loop();
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
The problem is that after the Looper.loop() no line of code is executed. I read that this is normal. I read many articles but I didn't understand how should I allow the execution of my while loop, and simultaneously process messages coming from my UI thread.
I hope the problem is clear. Suggest me the best solution.
don't do this:
while(true){
sleep(2000);
it's awfully bad on so many levels. if you need some background processing, use AsyncTasks, if you need a repeating event, use:
private Handler mHandler = new Handler();
private Runnable mSomeTask = new Runnable() {
public void run() {
doSomething();
}
};
and then somewhere in the code:
mHandler.postDelayed(mSomeTask, 100);
this will make your program work faster, jam less resources and basically be a better Android citizen.
I realize this is a very old question, but for periodic task scheduling, use this code:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> periodicTask = scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// do some magic stuff here
// note however, that you're running in background!
Log.d("PeriodicTask", "Doing something....");
}
}, 0 /* initial delay */, 10 /* start every 10 seconds */, TimeUnit.SECONDS);
and when you need to stop the periodic task, just issue
periodicTask.cancel(true);

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?

Android: Synchronize Methods on calling Remote Messenger Service

I want to write a module that connects to a remote Service.
The module can be used by developers in their apps to connect to a specific (bluetooth-)hardware. It should then connect to a single remoteservice that can be updated seperately in the market.
Because the Remote Service is only allowed to have a single thread for all the apps using it at the same time (Only one connection over bluetooth), I have chosen the messenger approach over AIDL.
My problem is now that I wanted to provide a synchronous method in my public API but the service returns in an handler - and as far as I have understood, the handler will allways wait for the current task to finish... So is there any way to get the answer in a differen thread?
the code of the synchronous method as I would like it to be:
responseDataSync = new Sync<ResponseData>();
// Send message
Message msg = Message.obtain(null, Constants.DATA, 1, 0);
send(msg);
try {
ResponseData responseData = responseDataSync.get();
// with responseDataSync using a countdown latch to synchronize...
// but it never fires thanks to the handler.
//etc...
Thanks in advance. I hope my question was somewhat understandable... ;)
/EDIT:
I want some method that returns data from the server. like
public ResponseData returnResponse(Data dataToSend)
but I can't wait for the service's return because then I am stuck in the thread what blocks the handler from returning...
A Handler is associated with a single message queue. If you send a Message from any Thread it will get enqueued there.
The Thread that receives all the Messages will get the appropriate message off the queue and handle it - one by one.
Meaning for you that if you have a Handler and you run all Messages through you handler you don't need synchronization since everything is handled in a single thread.
Edit: to create a Handler that handles messages in a background thread:
HandlerThread ht = new HandlerThread("threadName");
ht.start();
Looper looper = ht.getLooper();
Handler.Callback callback = new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
// handled messages are handled in background thread
return true;
}
};
Handler handler = new Handler(looper, callback);
handler.sendEmptyMessage(1337);
Edit2: wait on Messages might work like this
// available for all threads somehow
final Object waitOnMe = new Object();
HandlerThread ht = new HandlerThread("threadName");
ht.start();
Looper looper = ht.getLooper();
Handler.Callback callback = new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
// handled messages are handled in background thread
// then notify about finished message.
synchronized (waitOnMe) {
waitOnMe.notifyAll();
}
return true;
}
};
Handler handler = new Handler(looper, callback);
// in a different Thread:
synchronized (waitOnMe) {
handler.sendEmptyMessage(1337);
try {
waitOnMe.wait();
} catch (InterruptedException e) {
// we should have gotten our answer now.
}
}

Update textView from thread

In my OnCreate method I have created a thread that listens to incoming message!
In OnCreate() {
//Some code
myThread = new Thread() {
#Override
public void run() {
receiveMyMessages();
}
};
myThread.start();
// Some code related to sending out by pressing button etc.
}
Then, receiveMyMessage() functions…
Public void receiveMyMessage()
{
//Receive the message and put it in String str;
str = receivedAllTheMessage();
// << here I want to be able to update this str to a textView. But, How?
}
I checked this article but it did not work for me, no luck!
Any updates to the UI in an Android application must happen in the UI thread. If you spawn a thread to do work in the background you must marshal the results back to the UI thread before you touch a View. You can use the Handler class to perform the marshaling:
public class TestActivity extends Activity {
// Handler gets created on the UI-thread
private Handler mHandler = new Handler();
// This gets executed in a non-UI thread:
public void receiveMyMessage() {
final String str = receivedAllTheMessage();
mHandler.post(new Runnable() {
#Override
public void run() {
// This gets executed on the UI thread so it can safely modify Views
mTextView.setText(str);
}
});
}
The AsyncTask class simplifies a lot of the details for you and is also something you could look into. For example, I believe it provides you with a thread pool to help mitigate some of the cost associated with spawning a new thread each time you want to do background work.
Android supports message-passing concurrency using handlers and sendMessage(msg). (It is also possible to use handlers for shared-memory concurrency.) One tip is to call thread.setDaemon(true) if you wish the thread to die when the app dies. The other tip is to have only one handler and use message.what and a switch statement in the message handler to route messages.
Code and Code

Android: Issue using a handler and postDelayed()

I am trying to use a Handler to have some code execute in some amount of time.
This works well in 2 of my classes, but I'm running on an issue with this one:
One of my class extends Activity, and starts a Thread (that implements Runnable).
In my run() method, I have, as in my other classes:
mHandler = new Handler();
mHandler.removeCallbacks(StopRequest);
mHandler.postDelayed(StopRequest, 30000);
The program seems to complain:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
I don't understand why it is posting, could someone please help me?
EDIT: Adding parts of my code:
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(clientSocket.getOutputStream())), true);
out.println("VOICE_CALL_REQUEST");
// Wait for a response
// Set a timer (about 30 seconds)
mHandler = new Handler();
mHandler.removeCallbacks(StopRequest);
mHandler.postDelayed(StopRequest, 3000);
// Ready reply
InputStream stream = clientSocket.getInputStream();
BufferedReader data = new BufferedReader(new InputStreamReader(stream));
String line = data.readLine();
mHandler.removeCallbacks(StopRequest); // Timer is removed here
And if the timer hits 30 seconds:
// Stop a call request after some amount of time
private Runnable StopRequest = new Runnable() {
public void run() {
// Send a message to cancel the voice call
out.println("VOICE_CALL_CANCEL");
// Close the port
try {
clientSocket.close();
}
catch (IOException e) { finish(); }
}
};
Thanks a lot,
Jary
You can't create a handler in a worker thread (unless it has a looper, which you normally never do). The handler needs a looper, since it needs a point that evaluates all incoming messages and calls the handler when necessary.
Your handler needs to be in the UI thread. If you want to do something in a worker thread, you need to do your own message handling (you could use synchronized methods in your thread that set member variables which the worker thread checks), or, if your thread is more of the event-driven variety, you could really consider adding a looper - but again, that is not a common practice.
I found a solution. Defining the handler in the onCreate method fixes it. Rest of the code is identical. Thanks :)

Categories

Resources