Android, quick question from my book - android

I am a noob learning Android via a book, i have a quick question. My book code is pretty simple and looks like this:
My handler:
Handler handler=new Handler() {
#Override
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
}
};
My thread:
Thread background=new Thread(new Runnable() {
public void run() {
try {
for (int i=0;i<20 && isRunning.get();i++) {
Thread.sleep(1000);
handler.sendMessage(handler.obtainMessage());
}
}
catch (Throwable t) {
// just end the background thread
}
}
});
My question is here:
handler.sendMessage(handler.obtainMessage());
What the heck is "handler.obtainMessage()" ?
Doing a mouse over in Eclipse gives me a message that sounds like gibberish.
What message is it trying to "obtain"?

As described in the docs, it obtains a message from the message pool instead of creating a new one. (you need to send a message to the handler anyway):
Returns a new Message from the global message pool. More efficient
than creating and allocating new instances. The retrieved message has
its handler set to this instance (Message.target == this). If you
don't want that facility, just call Message.obtain() instead.
I'll try to elaborate:
You send a message to the handler. The message is added to the handler's thread queue and processed on the original thread. You need to send it a message, though you have nothing specific in the message that it uses (according to your handler code) so you just send an empty message, but instead of allocating a memory for a new message, the message is taken from the message pool, which is faster.
Hope this makes things clearer.
Regarding how to set a message with an int:
Message m = new Message();
Bundle b = new Bundle();
b.putInt("what", 5); // for example
m.setData(b);
handler.sendMessage(m);

Related

Can we pass messages to UI thread without reference to UI handler?

I have a complex class system, with many classes trying to update UI elements, so i searching for most efficient way to achieve this.In my opinion, using handler is the best solution (if you know the better way - please share it ). But there is some problem. If i use this code in separate thread - sended messages seems to be lost(without any warning), and UI handler don't dispatch them:
Handler handler = new Handler(Looper.getMainLooper());
Message message = handler.obtainMessage();
Parameters p = new Parameters(-1, -1);
p.setObdProtocols(ObdProtocols.values()[protocolPointer]);
message.obj = p;
handler.sendMessage(message);
This is code for UI handler:
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.d("OBD2DEBUGMODE", "MainActivity.handler: handling message: "+msg.what);
Parameters temp = (Parameters) msg.obj;
rpmTxt.setText(""+temp.getRpm());
throtleText.setText(""+temp.getThrotlePosition());
if(temp.getObdProtocols()!=null) {
protoTxt.setText(temp.getObdProtocols().toString());
}
}
};
Above code is not working... Why couldn't i just pass messages to UI thread queue holding reference to UI Looper? How can i update UI thread without passing some objects to background threads?

How do I receive a message using Handlers?

I've tried many ways to use handlers to receive messages on a background thread, I have not been successful.
Is there a sure fire way to test this? Is there a sample code I can use to see how it is done?
Yes, try the answer by #FoamyGuy. In the sample code he has sent back an empty message. I'm extending his code to pass strings. If you want to send some message back to the handler(eg: string), you can send some string or something else as follows:
Handler h = new Handler(){
#Override
public void handleMessage(Message msg){
if(msg.what == 1){
//Success
String msg = (String)msg.obj;
Log.d("", "Msg is:"+msg);
}else{
//Failure
String msg = (String)msg.obj;
Log.d("", "Msg is:"+msg);
}
}
};
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.
Message m = h.obtainMessage(1, "Success message string");
m.sendToTarget();
}else{
Message m = h.obtainMessage(0, "Your Failed!");
m.sendToTarget();
}
}
}
On a non-UI thread? All you need to do is create a Looper on that thread, then create the handler on it. That will automatically cause that Handler to be associated with that Looper. Then run Looper.loop
So
Looper.prepare();
Handler myHandler = new Handler();
Looper.loop()
and myHandler will be on the 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.
}
}

Android Handler not updating textview

Thought I would share some weird code with you all to see if I have done anything blindingly wrong.
I have passed a handler to a background thread to update the UI of the mainactivity (I know it is not the best way but this is supposed to be a quick and dirty test app)
Basically, the code appends a message on to the textview, like so:
uiHandler.post(new Runnable() {
#Override
public void run() {
Log.i("Text2Server", "Updating log with: " + logput);
logTextView.append(logput);
}
});
This happens everytime a UDP message is received, the log is output everytime perfectly, but the textview only updates on the first message, or sometimes not at all.
I assume it is something to do with my textview but I thought I would see if anyone has seen anything similar?
Thanks!
P.S. I have tried the basics, like using setText() instead of append() etc.
Does it output "Text2Server", "Updating log with: " + logput in the LogCat?
.post(Runnable r) this runnable is placed on the queue and will be run later when the thread that is attached executes.
Maybe, the handler does not gain access to the ui thread, this assumption can be wrong as well.
Try another way.
Instantiate the handler:
Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String logPutFromThread=msg.getData().getString("somekey");
Log.i("Text2Server", "Updating log with: " + logPutFromThread);
logTextView.append(logPutFromThread);
}
};
and from the Runnable of the thread do
Runnable updateActivityUi = new Runnable(){
#Override
public void run() {
//do something before you send the message
Message msg = new Message();
msg.peekData().putString("somekey", logput)
handler.sendMessage(msg)
}};

get main thread's message queue and handler

How do I get the message queue of the main thread from another thread? Looper.getMainLooper() gets the main thread's looper but I am unable to find a way to get the MessageQueue for another thread's looper. Moreover, how do I get the handler for the main looper? I am unable to find any way to get it.
#r.v,
I had a similar need. I wanted to know when the MessageQueue is empty and when I post something for it to do and I want to know when it becomes empty with nothing remaining to do. I looked at the MessageQueue.IdleHandler and found that it didn't behave as I wanted to I came up with another solution.
In my case I wanted to use the Looper/Handler mechanism to sequentially execute file downloads. Basically each download I want to execute is wrapped in a Runnable. I only want one at a time to be running, so this pattern works well without having to dig into the nuts and bolts of a more involved threading solution. Additionally, I wanted to know when I first put something into the queue and it begins its work, and wanted to know when it was completely done (queue is empty).
I was able to use the handler's message mechanism to achieve this. The messages are handled in sequence with the Runnables, so you can strategically place messages in the queue to help you know the conditions of the queue. Unlike with Runnables in the Handler's queue, there are some query and removal abilities for messages that ultimately provide the solution.
What I do is each time I add a runnable to the Handler (via Handler.post), I also remove all instances of the custom QUEUE_EMPTY message, then add a fresh QUEUE_EMPTY message. This ensures that I have a QUEUE_EMPTY message at the end of the queue. Once I encounter the QUEUE_EMPTY message in my subclassed Handler, I know that I'm at the end of the queue. Additionally, if I don't find a QUEUE_EMPTY message in the queue when I go to add a runnable, I know that the queue was empty and the thread was idle.
As some will quickly point out, there are some real inefficiencies with this solution. Having to iterate through the queue for these "marker" messages could be a real performance issue if there were a large number of entries in the queue. In my case, I'm dealing with only a handful of file downloads at a time so any performance penalties are negligible. If you have a similar situation, I think this is a pretty reasonable solution. It would have been nice for the Android SDK to provide these basic abilities to the MessageQueue. I agree ideally you wouldn't want to mess with the MessageQueue, but knowing when it is idle/working/empty seem like reasonable things and I'm sure there are numbers of scenarios when there is value knowing these things.
class DownloaderThread extends Thread
{
private static final int QUEUE_EMPTY = 9999;
private MyHandler handler;
#Override
public void run()
{
try
{
Looper.prepare();
handler = new MyHandler();
Looper.loop();
}
catch (Throwable t)
{
Log.e(TAG, "halted due to an error", t);
}
}
public void post(Runnable r)
{
if(!handler.hasMessages(QUEUE_EMPTY))
{
Log.v(TAG, "Download queue was empty. First element being added.");
}
handler.post(r);
handler.removeMessages(QUEUE_EMPTY);
handler.sendEmptyMessage(QUEUE_EMPTY);
}
class MyHandler extends Handler
{
#Override
public void handleMessage(Message msg)
{
if(msg.what == QUEUE_EMPTY)
{
Log.v(TAG, "Download runnable queue is empty!");
}
}
}
};
After you get the main threads looper, you should just be able to call myQueue to get the main threads MessageQueue.
http://developer.android.com/reference/android/os/Looper.html#myQueue%28%29
Use the Handler class to interact with a Looper's message queue.
To interact with the main thread's message queue,
Handler mainHandler = new Handler(Looper.getMainLooper(), new Callback() {
#Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
});
mainHandler.post(...);
mainHandler.sendMessage(...);
mainHandler.removeMessage(...);
Now you can send, remove and receive messages.

Categories

Resources