Error when updating UI from thread using Handler
I am attempting to send data to a server in a separate thread and have it send messages back to a Handler I have in my main thread to update the UI.
I have it working for the first 2 messages it sends, but then for some reason I get a CalledFromWrongThreadException.
I am adding comments to the code below to show what works and where it bombs out.
Any help would Be greatly appreciated thank you.
//Started in onCreate()
Thread thread = new Thread(new Runnable(){
public void run() {
sendFiles();
}
});
thread.start();
private void sendFiles(){
if(new File(filePath+"/description.txt").isFile()){ //The messages sent from in this if() work but the others bomb.
Message message = progressTextHandler.obtainMessage();
message.obj = (progressText.getText() + "\n Started Sending description.txt\n");
progressTextHandler.sendMessage(message);
if(sendToServer(filePath+"/description.txt")){
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Finished Sending description.txt\n");
progressTextHandler.sendMessage(message1);
}else{
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Error Sending description.txt\n");
progressTextHandler.sendMessage(message1);
}
}
for(int x = 0; x<getIntent().getExtras().getInt("numOfAudio"); x++ ){
Message message = progressTextHandler.obtainMessage();
message.obj = (progressText.getText() + "\n Started Sending " + getIntent().getExtras().getString("audio"+String.valueOf(x)) + "\n");
progressTextHandler.sendMessage(message);
if(sendToServer(getIntent().getExtras().getString("audio"+String.valueOf(x)))){
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Finished Sending " + getIntent().getExtras().getString("audio"+String.valueOf(x)) + "\n");
progressTextHandler.sendMessage(message1);
}else{
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Error Sending " + getIntent().getExtras().getString("audio"+String.valueOf(x)) + "\n");
progressTextHandler.sendMessage(message1);
}
}
for(int k = 0; k<getIntent().getExtras().getInt("numOfBrowsed"); k++){
Message message = progressTextHandler.obtainMessage();
message.obj = (progressText.getText() + "\n Started Sending " + getIntent().getExtras().getString("pic"+String.valueOf(k))+"\n");
progressTextHandler.sendMessage(message);
if(sendToServer(getIntent().getExtras().getString("pic"+String.valueOf(k)))){
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Finished Sending " + getIntent().getExtras().getString("pic"+String.valueOf(k))+"\n");
progressTextHandler.sendMessage(message1);
}else{
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Error Sending " + getIntent().getExtras().getString("pic"+String.valueOf(k))+"\n");
progressTextHandler.sendMessage(message1);
}
}
for(int l = 0; l<getIntent().getExtras().getInt("numOfStills"); l++){
Message message = progressTextHandler.obtainMessage();
message.obj = ("\n Started Sending " + getIntent().getExtras().getString("still"+String.valueOf(l))+"\n");
progressTextHandler.dispatchMessage(message);
if(sendToServer(getIntent().getExtras().getString("still"+String.valueOf(l)))){
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Finished Sending " + getIntent().getExtras().getString("still"+String.valueOf(l))+"\n");
progressTextHandler.dispatchMessage(message1);
}else{
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Error Sending " + getIntent().getExtras().getString("still"+String.valueOf(l))+"\n");
progressTextHandler.dispatchMessage(message1);
}
}
for(int m = 0; m<getIntent().getExtras().getInt("numOfVideos"); m++){
Message message = progressTextHandler.obtainMessage();
message.obj = (progressText.getText() + "\n Finished Sending " + getIntent().getExtras().getString("video"+String.valueOf(m))+"\n");
progressTextHandler.dispatchMessage(message);
if(sendToServer(getIntent().getExtras().getString("video"+m))){
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Finished Sending " + getIntent().getExtras().getString("video"+String.valueOf(m))+"\n");
progressTextHandler.dispatchMessage(message1);
}else{
Message message1 = progressTextHandler.obtainMessage();
message1.obj = (progressText.getText() + "\n Error Sending " + getIntent().getExtras().getString("video"+String.valueOf(m))+"\n");
progressTextHandler.dispatchMessage(message1);
}
}
}// end of sendFiles()
progressTextHandler = new Handler(){ //my handler that also lives in onCreate()
public void handleMessage(Message msg){
progressText.setText((String)msg.obj);
}
};
This is the printStackTrace that i get.
10-03 23:51:20.105: WARN/dalvikvm(5760): threadid=10: thread exiting with uncaught exception (group=0x40018560)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): FATAL EXCEPTION: Thread-11
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.view.ViewRoot.checkThread(ViewRoot.java:2932)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.view.ViewRoot.invalidateChild(ViewRoot.java:642)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:668)
1开发者_高级运维0-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.view.View.invalidate(View.java:5255)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.widget.TextView.invalidateCursor(TextView.java:3983)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.widget.TextView.spanChange(TextView.java:6797)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.widget.TextView$ChangeWatcher.onSpanAdded(TextView.java:6926)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.text.SpannableStringBuilder.sendSpanAdded(SpannableStringBuilder.java:979)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:632)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:535)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.text.Selection.setSelection(Selection.java:74)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.text.Selection.setSelection(Selection.java:85)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.text.method.ArrowKeyMovementMethod.initialize(ArrowKeyMovementMethod.java:268)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.widget.TextView.setText(TextView.java:3003)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.widget.TextView.setText(TextView.java:2883)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.widget.EditText.setText(EditText.java:78)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.widget.TextView.setText(TextView.java:2858)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at com.vincentjuliano.jreporter.SubmitServer$2.handleMessage(SubmitServer.java:104)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at android.os.Handler.dispatchMessage(Handler.java:99)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at com.vincentjuliano.jreporter.SubmitServer.sendFiles(SubmitServer.java:227)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at com.vincentjuliano.jreporter.SubmitServer.access$4(SubmitServer.java:173)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at com.vincentjuliano.jreporter.SubmitServer$1$1.run(SubmitServer.java:70)
10-03 23:51:20.144: ERROR/AndroidRuntime(5760): at java.lang.Thread.run(Thread.java:1019)
10-03 23:51:20.167: WARN/ActivityManager(1322): Force finishing activity com.vincentjuliano.jreporter/.SubmitServer
I think it's a bit too late but I'll give you my opinion: the problem is that you use handler.dispatchMessage in several lines (while you are using handler.sendMessage in the previous lines, which is correct).
While dispatchMessage invokes the handler immediately in the same thread where the dispatchMessage method was called, with sendMessage the message will be received in handleMessage(Message), in the thread attached to this handler.
So it would just work if you replace those dispatchMessage with sendMessage, and the code will be cleaner than using the runOnUiThread.
I hope this is useful to someone :)
In the stack trace, it appears the exception is coming from the fact that
com.vincentjuliano.jreporter.SubmitServer$2.handleMessage(SubmitServer.java:104) 10-03
is trying to update the UI but isn't on the UI thread. Consider using Activity.runOnUiThread()
to update the UI. Using this function, you don't need to worry about Handlers and Loopers.
For Updating
a the UI
from a non-UI thread
you need to use activity.this.runOnUiThread()
method this will execute the code on the UI thread.
Activity_name.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
精彩评论