Android:android.view.ViewRoot$CalledFromWrongThreadException - 如何解决这个问题?

5

我目前正在开发的一个应用程序正在与服务器通信,通信过程在其自己的线程中运行。有异步调用 - 例如login()和onLoginResponse()。

login()在主活动中被调用,并且响应也在主活动中处理(onLoginResponse())。在onLoginResponse()方法中,有一个updateGUIState()方法,它修改布局元素:

private void updateGUIState() {

    Log.i(TAG, "executing updateGUIState");

    arrangeLayoutElements();
    txtTime.setText(mStrRecordingTime);
    if (settings.isRecording()) {
        //btnAction.setText("Stop");
        btnAction.setImageResource(R.drawable.button_stop);
    } else {
        //btnAction.setText("Capture");
        btnAction.setImageResource(R.drawable.button_record);
    }

    //set privacy level text
    if (settings.getPrivacyLevel() == 0) {
        txtPrivacyLevel.setText("Private");
    } else if (settings.getPrivacyLevel() == 1) {
        txtPrivacyLevel.setText("Public");
    }

    if (settings.isMute()) {
        muteIcon.setIconImage(R.drawable.ic_volume_off_small);
    } else {
        muteIcon.setIconImage(R.drawable.ic_volume_small);
    }

    if (mIsUploading) {
        txtUploadingText.setVisibility(View.VISIBLE);
        uploadingProgressBar.setVisibility(View.VISIBLE);
    } else {
        txtUploadingText.setVisibility(View.INVISIBLE);
        uploadingProgressBar.setVisibility(View.INVISIBLE);
    }

    if (mEncoderConnection != null) {
        txtConnectionStatus.setText("Connected");
    } else {
        txtConnectionStatus.setText("Disconnected");
    }
}

当执行到这个方法时(从onLoginResponse()调用),应用程序会崩溃,并且日志显示以下消息:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.


有没有人知道如何修改逻辑,以便在修改布局之前切换到适当的线程并解决问题?

谢谢!
3个回答

17

尝试使用Handler

onLoginResponse()是否是回调函数?如果是,问题可以通过Handler来解决。

onLoginResponse()中,

hRefresh.sendEmptyMessage(REFRESH);


    Handler hRefresh = new Handler(){
    @Override
    public void handleMessage(Message msg) {
    switch(msg.what){
         case REFRESH:
                /*Refresh UI*/
                updateGUIState();
                break;
       }
    }
};

我希望很久以前就找到了这个答案,我遇到了完全相同的问题,花了我大约一周的时间才找到解决方案,而这正是您所提到的。 - aryaxt
我找到了至少5个不同的答案来解决这个异常。只有这一个对我起作用! - Memet Olsen

3

updateGUIState()需要在UI线程上运行。一种可能的解决方法是使用Runnable实现您的GUI更新,并使用您的Runnable调用runOnUiThread方法。


0
补充bhatt4982的回答,您还可以调用handler.post(onLoginThread),其中onLoginThread是一个Thread,其可运行内容将在GUI线程内运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接