I've a little problem.I try to give a string to a handler.
I tried it with bundle.putString("key","String"); , but if i try to get the string, i got a nullpointerException. Can somebody tell me what i'm doing wrong?
Code:
Message msg = new Message();
Bundle b = new Bundle();
b.putString("note","4.25");
b.putString("fach", "Math");
Log.d("DEBUG ",b.getString("note")+" "+fach); //--> Here isn't a nullPointerException
msg.setData(b);
handler.sendMessage(msg);
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle b = msg.getData();
Log.d("DEBUG,HANDLER","note "+b.getString("note")+" fach"+b.getString("fach")); //Throws 2 times null
}
}
Hope you can help me. Sorry for the bad english :)
This isn't a lot of code to go on, but I would try using Message.obtain() instead of new Message(). I'm not convinced that the message you're receiving in handleMessage() is the one you sent in handler.sendMessage(). Both the sendMessage() and the handleMessage() have to be called on the same Thread, and you have to make sure you haven't put any other Message objects in the handler's MessageQueue.
Related
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?
I have a UI created in an activity which creates a handler for receiving messages.
I then launch a second thread for network communication. This second thread sends messages back to the UI thread via the UI threads handler.
All works OK as long as I send integer values.
However, if I set the objvalue to an object such as a string, when it arrives in the handler it has been set back to null.
The handler is declared like this :
private static class MsgHandler extends Handler
{
private CommsActivity m_parent;
public MsgHandler(CommsActivity parent)
{
m_parent = parent;
}
#Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case R.integer.msg_progress :
m_parent.ShowProgress(msg.arg1);
break;
case R.integer.msg_error :
m_parent.ShowError(msg.arg1, (String)msg.obj);
break;
}
}
}
When I need to send a message from the second thread, I call it in this manner :
msg = m_hMsgHandler.obtainMessage();
msg.what = m_iNormalMsgId;
msg.arg1 = R.integer.activation_lockout;
msg.obj = new String(strResponse);
msg.sendToTarget();
The MsgHandlerinstance is passed into the thread runnable as a parameter and stored for later use.
I have also tried using a Bundle instance, but this also is set to NULL.
Note that I am working with Android 4.4.
What do I need to do to overcome this limitation ?
try to send message using handler.
hope it helps
msg = m_hMsgHandler.obtainMessage();
msg.what = m_iNormalMsgId;
msg.arg1 = R.integer.activation_lockout;
msg.obj = new String(strResponse);
m_hMsgHandler.sendMessage(msg);
and check, that you process exactly this message (I see in yuor samples set msg.what = m_iNormalMsgId but in switch process case R.integer.msg_progress like msg.arg1 = R.integer.activation_lockout;)
This is how I'd try it:
m_hMsgHandler.sendMessage(
m_hMsgHandler.obtainMessage(
m_iNormalMsgId,
R.integer.activation_lockout,
0,
new String(strResponse)
);
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.
I am trying to get the url of the image touched by a user in a WebView.
I use getHitTestResult() but I need to handle cases where getHitTestResult() return UNKNOWN_TYPE.
The documentation suggests requestFocusNodeHref (Message hrefMsg) but I don't understand what the Message should be.
Thank you for any idea.
Answering my own question here.
So this is how it works. The message in question must be sent to a Handler that will handle the request.
/*
* Used to get the result of requestFocusNodeHref(msg)
*/
class MyHandler extends Handler{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String src = msg.getData().getString("src");
launchImageSaveAs(src);
}
}
Then, somewhere in your code, for example in OnLongClickListener you create a new message and set the handler as a target and finally call requestFocusNodeHref
if(result.getType() == HitTestResult.UNKNOWN_TYPE){
Message msg = new Message();
msg.setTarget(new MyHandler());
webview.requestFocusNodeHref(msg);
}
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);