How do you call a method on the UIThread from a Thread? - java

While it is useful to run long standing tasks on their own thread running code in the UIThread is necessary in order to update the UI components. Otherwise your application will throw the CalledFromWrongThreadException during execution. How can you run code on the UIThread?

There are a number of ways this can be achieved:
Use runOnUiThread() method call
Use post() method call
Use the Handler framework
Use a Broadcasts and BroadcastReceiver (optionally with LocalBroadcastManager)
Use an AsyncTask's onProgressUpdate() method
Method 1:
runOnUiThread(new Runnable() {
#Override
public void run() {
// do something
}
});
Read more: http://www.intertech.com/Blog/android-non-ui-to-ui-thread-communications-part-1-of-5/#ixzz3hnx3hdS5

Yes you can use handler to communicate between Worker Thread and UI Thread, put below code snippet into worker thread from which you want to update your UI,
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("file", pdfPath);
message.setData(bundle);
handler.sendMessage(message); // pass handler object from activity
put Handler related code into Activity class
Handler handler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
String filePath = msg.getData().getString("file"); // You can change this according to your requirement.
}
};
If you aren't familiar with Handler mechanism then first read following link, it will help you
https://developer.android.com/training/multiple-threads/communicate-ui.html

Related

Message sent to the UI thread never arrives

This topic has been discussed many times so far, but still haven't managed got it working.
My MainActivity has a property called Handler mHandlerUi; which is initialized in its constructor
mHandlerUi = new Handler() {
#Override
public void handleMessage(Message msg){
onMessageArrive(msg);
}
};
Later on in the code, In another class, during construction time i initialize another Handler property
mHandlerToUi = new Handler(Looper.getMainLooper());
So during the thread's life time, the following code snippet is executed X times.
Message msg = mHandlerToUi.obtainMessage();
msg.what = ConstMessages.MSG_NEW_GPS_POINT;
msg.setData(bundleContet);
mHandlerToUi.sendMessage(msg);
Unfortunately the message never arrives the MainActivity's Looper, Both threads uses the same UI's looper,
What am i missing over here?
If I understand you correctly, you have initiated two handlers and you want to pass the message from one to another?
Perhaps you should pass the handler to the second class instead. So in your MainActivity you have
mHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message inputMessage) {
onMessageArrive(msg);
}
}
and pass this mHandler to your second class via constructor or setter method.
Each Handler handle its messages. The Looper is used for running a Handler on a specific Thread.
If you create two Handler, there will not communicate. There will only share the same Looper that run on a Thread.
You can find good answers on What is the relationship between Looper, Handler and MessageQueue in Android?

Capturing executor for current thread

I'm using ListenableFuture from Guava, and one nice thing about them is that one pass Executor to the Futures.addCallback method, that is, ask to execute the callback on a given thread/executor.
In my Android application, I want to be able to start the asynchronous execution based on ListenableFuture in the UI thread, and schedule a callback which is also executed also on the UI thread. Therefore, I'd like to somehow submit the UI thread executor to the Futures.addCallback method mentioned above. How to achieve that?
Or, in other words, I want to have an executor for the UI thread. Is it available already in Android, or, if I have to create my own, how do I do that?
EDIT: As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
I think I've see some implementation doing that. The basic Idea is roughly
class UiThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
You can delegate to run anything in the main thread by passing it to a handler for the main thread.
Edit: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/android/MainThreadExecutor.java for example
Edit2: You can configure the handler like e.g. SensorManager#registerListener(..., Handler handler) allows you to do.
class HandlerThreadExecutor implements Executor {
private final Handler mHandler;
public HandlerThreadExecutor(Handler optionalHandler) {
mHandler = optionalHandler != null ? optionalHandler : new Handler(Looper.getMainLooper());
}
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
The advantage over using the current thread's looper is that it makes it explicit which Looper you use. In your solution you take the Looper of whatever thread calls new ExecuteOnCaller() - and that's often not the thread you run code in later.
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
Looper, Handler and the message queue behind all that logic are made of mostly pure Java. The problem with a generic solution is that you can't "inject" code to run into a thread. The thread must periodically check some kind of task queue to see if there is something to run.
If you write code like
new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("Hello");
}
}
}).start();
Then there is no way to make that thread do anything else but constantly print "Hello". If you could do that it would be like dynamically inserting a jump to other code into the program code. That would IMO be a terrible idea.
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
Runnable codeToRunInThisThread = queue.take();
codeToRunInThisThread.run();
}
} catch (InterruptedException ignored) {}
}
}).start();
On the other hand is a simple thread that loops forever on a queue. The thread could do other tasks in between but you have to add a manual check into the code.
And you can send it tasks via
queue.put(new Runnable() {
#Override
public void run() {
System.out.println("Hello!");
}
});
There is no special handler defined here but that's the core of what Handler & Looper do in Android. Handler in Android allows you to define a callback for a Message instead of just a Runnable.
Executors.newCachedThreadPool() and similar do roughly the same thing. There are just multiple threads waiting on code in a single queue.
As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
The generic answer is No. Only if there is a way to inject code to run in that thread.
Based on asnwer from #zapl, here is my implementation, which also answers the edited (extended) question: https://gist.github.com/RomanIakovlev/8540439
Figured out I'll also put it here, in case if link will rot some day:
package com.example.concurrent;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
/**
* When the calling thread has a Looper installed (like the UI thread), an instance of ExecuteOnCaller will submit
* Runnables into the caller thread. Otherwise it will submit the Runnables to the UI thread.
*/
public class ExecuteOnCaller implements Executor {
private static ThreadLocal<Handler> threadLocalHandler = new ThreadLocal<Handler>() {
#Override
protected Handler initialValue() {
Looper looper = Looper.myLooper();
if (looper == null)
looper = Looper.getMainLooper();
return new Handler(looper);
}
};
private final Handler handler = threadLocalHandler.get();
#Override
public void execute(Runnable command) {
handler.post(command);
}
}
My pattern to use it would be like this:
/**
* in SomeActivity.java or SomeFragment.java
*/
Futures.addCallback(myModel.asyncOperation(param), new FutureCallback<Void>() {
#Override
public void onSuccess(Void aVoid) {
// handle success
}
#Override
public void onFailure(Throwable throwable) {
// handle exception
}
}, new ExecuteOnCaller());
Use com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD.
An Executor that uses the main application thread.
Source: Android docs
The tasks APIs are part of Google Play services since version 9.0.0.
For Android UI thread executor use:
ContextCompat.getMainExecutor(context)
To address your question and extended question to create an Executor that simply runs on the current thread and avoids Android classes:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
See documentation: https://developer.android.com/reference/java/util/concurrent/Executor

sendBroadcast not working from WorkerThread

i want to send a Broadcast from a FromTowerThread with the following method:
void postToService(final String string){
Handler handler = new Handler();
handler.post(new Runnable(){
#Override
public void run() {
context.sendBroadcast(new Intent(string));
}
});
}
My context is 'this' (my service):
FromTowerThread ftt = new FromTowerThread(this);
(just for completeness my constructor in FromTowerThread):
public FromTowerThread(Context context){
this.context=context;
}
The Error i get is "Can't create handler inside thread that has not called Looper.prepare()".
I don't know how to fix this error, all threads i found about this topic could not help me to understand this.
Thanks in advance!
Chris
change the statement
Handler handler = new Handler();
to
Handler handler = new Handler(Looper.getMainLooper());
Post can only be done from a Handler in a thread that called Looper.prepare().
I'm assuming here that the thread that calls void postToService(final String string) is some type of background thread. Usually the UI thread does call Looper.prepare() meaning that you would have to create the Handler inside the UI thread.
but just as a general suggestion, I'm pretty sure you can just eliminate all of this and just call the broadcast straight away:
void postToService(final String string){
context.sendBroadcast(new Intent(string));
}
The Error i get is "Can't create handler inside thread that has not called Looper.prepare()".
If you are extending Thread, try extending HandlerThread instead. A HandlerThread has a Looper already. (Or you can call Looper.prepare() and Looper.loop() yourself in a regular Thread.)
Otherwise you can do a few things to use the main Thread's Looper. For instance create the Handler in the main Thread and pass it to your worker Thread or even pass a View from the UI Thread and call view.post(Runnable) to execute that Runnable on the UI Thread.

Looper.loop not called but code in handler is still executed

I am trying to understand how looper.loop works, and when to use it in my code.
I have a bound service that has a runnable. Inside I have a handler that is used to hold code that updates the Ui. Here is the code.
private Runnable builder = new Runnable() {
public void run()
{
while(isThreadStarted == true)
{
if (newgps == 1)
{
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
//some code that updates UI
}
}
}
}
}
looper.prepair
}
From what I read looper. prepare has to be called before the handler is made. But I noticed I didn’t do that but this code still works. How is this possible?
I want to fix this but im not sure where to put loper.loop. Because this handler is called many many times. Would it be ok if i put looper.loop right after .prepare? Then .quit when isThreadStarted == false?
The Handler is associated with the UI thread, since you attach it to Looper.getMainLooper(). The UI thread prepares its Looperon application start, so that is nothing the application has to do itself.
By using Looper.getMainLooper(), you get Handler of main thread and you are posting on main thread. Main thread has its looper prepared by system already when it is created.

Showing ok cancel Dialogbox through thread

I have an Android service which spawns a thread.This thread waits for network data and after receiving that data I want to show Ok Cancel Dialogbox.
I was getting exception can't create handle that should have Looper.prepare().I added Looper.prepare() and Looper.loop() then now I am not getting any exception but its waiting infinitely.
Instead of using a sole thread it's better to use an AsyncTask which is also a speacialized thread for Android.
You can wait for data in the AsyncTask's doInBackGround method and when you received data you can call publishProgress() which will invoke onProgressUpdate method of AsyncTask.
At onProgressUpdate you can update the UI without blocking the main thread and also this is the preferred way of doing long time operations in background like network listening etc.
Check AsyncTask for more info and how to use it.
http://developer.android.com/reference/android/os/AsyncTask.html
You can invoke the UI thread(showing alert dialog) in non-UI thread by using handlers as like below code
new Thread(new Runnable()
{ public void run()
{
try {
///do your stuff in
mHandlerShowDialog.post(mUpdateShowDialog);
///do your struff
}
} ).start();
final Handler mHandlerShowDialog= new Handler();
final Runnable mUpdateShowDialog = new Runnable() {
public void run() {
// show your dialog here
}
};

Categories

Resources