使用Handler从线程更新UI时出错

时间:2011-10-04 04:05:59

标签: android multithreading

我正在尝试将数据发送到单独线程中的服务器,并让它将消息发送回我主线程中的Handler以更新UI。

我让它为它发送的前2条消息工作,但由于某种原因我得到了CalledFromWrongThreadException。

我正在为下面的代码添加注释,以显示哪些内容有用,哪些内容有效。

非常感谢任何帮助。谢谢。

    //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);
        }
    };

这是我得到的printStackTrace。

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)
10-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

3 个答案:

答案 0 :(得分:1)

在堆栈跟踪中,似乎异常来自

这一事实
com.vincentjuliano.jreporter.SubmitServer$2.handleMessage(SubmitServer.java:104) 10-03 

正在尝试更新UI但不在UI线程上。考虑使用Activity.runOnUiThread()更新UI。使用此功能,您无需担心处理程序和循环程序。

答案 1 :(得分:1)

对于Updating来自UI的{​​{1}}您需要使用non-UI thread方法,这将执行activity.this.runOnUiThread()上的代码

UI thread.

答案 2 :(得分:1)

我认为这有点太晚了但我会给你我的意见:问题是你在几行中使用handler.dispatchMessage(当你在前面的行中使用handler.sendMessage时,这是正确的)。 / p>

虽然dispatchMessage在调用dispatchMessage方法的同一线程中立即调用处理程序,但sendMessage将在handleMessage(Message)中接收消息,在附加到此处理程序的线程中

所以如果你用sendMessage替换那些dispatchMessage就行了,而且代码比使用runOnUiThread更干净。

我希望这对某人有用:)