Android:android.view.ViewRoot$CalledFromWrongThrea

2020-02-01 04:56发布

An application I am currently developing is communicating with the server and the communication process runs in its own thread. There are asynchronous calls - for example login() and onLoginResponse().

login() is called in the main activity and the response is handled in main activity as well (onLoginResponse()). In onLoginResponse() method there is updateGUIState() method which modifies layout elements:

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

When the execution reaches this method (when called from onLoginResponse()) the application crashes and the log displays the following message:

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

Does anyone know how it is possible to modify the logic in order to switch to appropriate thread before modifying the layout and fix the problem?

Thanks!

3条回答
▲ chillily
2楼-- · 2020-02-01 05:47

updateGUIState() needs to be run on the UI thread. A possible solution is to implement your GUI update in a Runnable, and call the runOnUiThread method with your runnable.

查看更多
beautiful°
3楼-- · 2020-02-01 05:52

To add to bhatt4982's response, you can also call handler.post(onLoginThread), where onLoginThread is a Thread whose runnable will run inside the GUI thread.

查看更多
迷人小祖宗
4楼-- · 2020-02-01 05:53

Try Handler.

Is onLoginResponse() is a callback function?
If it is, the problem can be solved by Handler.

In onLoginResponse(),

hRefresh.sendEmptyMessage(REFRESH);


    Handler hRefresh = new Handler(){
    @Override
    public void handleMessage(Message msg) {
    switch(msg.what){
         case REFRESH:
                /*Refresh UI*/
                updateGUIState();
                break;
       }
    }
};
查看更多
登录 后发表回答