android-How to solve 'android android.view.ViewRootImpl$CalledFromWrongThreadException

1. The purpose of this post

I would demo how to solve this error when using do some UI operations in a thread:

The code(updateUI from a thread inside an activity or fragment):

public class MyActivity extends AppcompatActivity {
    private class CheckThread extends Thread {
            @Override
            public void run() {
                try {
                        updateUI();
                    }
                 catch (Exception ex) {
                    LogUtils.error("",ex);
                 }
            }
    }

    public void onCreate(...) {
        (new CheckThread()).start();
    }
    private void updateUI() {
        myView.setVisibility(View.VISIBLE);//show some view in a thread
    }
}

Run the app, we get this error:

E/MyTest: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7753)
        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1225)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.requestLayout(View.java:23093)
        at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
        at android.view.View.requestLayout(View.java:23093)
        at android.view.View.setFlags(View.java:14102)
        at android.view.View.setVisibility(View.java:9992)
        at com.tom.Fragment.showConfirmButton(Fragment.java:87)
        at com.tom.Presenter.onGotToken(Presenter.java:188)
        at com.tom.Presenter.access$800(Presenter.java:43)
        at com.tom.Presenter$CheckThread.run(Presenter.java:168)

2. Environments

  • Android Studio 3.x

3. Solution and Code

Because android system do not allow the UI operations to run in the non-UI thread, so you can change the code like this:

public class MyActivity extends AppcompatActivity {
    private class CheckThread extends Thread {
            @Override
            public void run() {
                try {
                        updateUI();
                    }
                 catch (Exception ex) {
                    LogUtils.error("",ex);
                 }
            }
    }

    public void onCreate(...) {
        (new CheckThread()).start();
    }
    private void updateUI() {
        myView.getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                myView.setVisibility(View.VISIBLE);
            }
        });
        
    }
}

Build and run the app, everything works fine.