Message sent to the UI thread never arrives - java

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?

Related

How do I use Looper within requestLocationUpdates?

I am a beginner in Android development. I'm creating a small app that takes a picture after a device reaches a certain speed. However, one of the parameters of the requestLocationUpdates method (which of course is used to track the user’s location), requires a Looper in its third prameter. How would I create a looper? And where should it go? My requestLocationUpdates method currently looks like this: (I have null in place of a Looper)
protected void requestUpdates() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
MC.requestLocationUpdates(locRequest, mLocationCallback, null);
}
}
The Android dev site has advised to do something like this:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
However, I still have no clue where to put this code, what to do with it once I put it in, or how I can use it within my MainActivity. Any suggestions will be greatly appreciated.
Create a looper by following code.
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
// Now get the Looper from the HandlerThread
// NOTE: This call will block until the HandlerThread gets control and initializes its Looper
Looper looper = handlerThread.getLooper();
and pass object of looper in requestLocationUpdates() as peramiter as following.
MC.requestLocationUpdates(locRequest, mLocationCallback, looper);
As #Markus said in his comments, you will probably be required to pass this if your Activity has implemented LocationListener interface. That is the 3rd parameter you will need instead of a Looper.
If your callback does not access disk and is quick you can pass null.
Quoting documentation, you should pass
a Looper object whose message queue will be used to implement the callback mechanism, or null to make callbacks on the calling thread
If you call requestLocationUpdates on the main thread and pass null as Looper, you'll receive callbacks on the main thread.
You can't access network from the main thread and you shouldn't perform any I/O operations on the main thread. Your UI would start lagging.

Android: How to Use Handlers With Thread Class and UI Thread (MainActivity)

I viewed the answer here: Updating Android UI using threads
But I am not able to understand how to instantiate the handler in the background thread to match the UiThread.
I just want to be clear and say that im using are 2 entirely separate classes.
UiThread Handler Code:
final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
if(msg.what==UPDATE_IMAGE){
images.get(msg.arg1).setImageBitmap((Bitmap) msg.obj);
}
super.handleMessage(msg);
}
};
Background Thread Handler code:
if(dataArrives){
Message msg = handler.obtainMessage();
msg.what = UPDATE_IMAGE;
msg.obj = bitmap;
msg.arg1 = index;
handler.sendMessage(msg);
}
In the background class, im getting "handler" as undefined.
Please show the entire thread classes in your answer if you can.

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

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

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.

Categories

Resources