Only the original thread that created a view hiera

2019-03-14 12:01发布

问题:

This question already has an answer here:

  • Android “Only the original thread that created a view hierarchy can touch its views.” 22 answers

I'm only a beginner so please forgive me for asking possibly a stupid question


I don't understand the meaning of Only the original thread that created a view hierarchy can touch its views.

Please can someone teach me why this error is occurring and how to solve this problem.

ThankYou

This is my class

public class MainActivity extends Activity {
    TextView title;
    Random   random  = new Random();
    int      counter = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.startup);
        startingUp();
    }

    private void startingUp() {
        Thread timer = new Thread() { //new thread         
            public void run() {
                Boolean b = true;
                try {
                    do {
                        counter++;
                        title();
                        sleep(1000);
                        title.clearComposingText();

                    }
                    while (b == true);
                } catch (IntruptedException e) {
                    e.printStackTrace();
                }
                finally {
                }
            };
        };
        timer.start();
    }

    public void title() {
        title = (TextView) findViewById(R.id.tvTitle);
        switch (random.nextInt(2)) {
            case 0:
                title.setGravity(Gravity.RIGHT);
                break;
            case 1:
                title.setGravity(Gravity.CENTER);
                break;
            case 2:
                title.setGravity(Gravity.LEFT);
                break;
        }
        title.setTextColor(Color.rgb(random.nextInt(250), random.nextInt(250), random.nextInt(250)));
        title.setTextSize(random.nextInt(55) + 10);
    }
}

And this is my LogCat

02-20 10:53:19.293: I/Adreno200-EGLSUB(5816): <ConfigWindowMatch:2078>: Format RGBA_8888.
02-20 10:53:19.303: D/memalloc(5816): /dev/pmem: Mapped buffer base:0x5c914000 size:14135296 offset:10366976 fd:64
02-20 10:53:19.303: E/(5816): Can't open file for reading
02-20 10:53:19.303: E/(5816): Can't open file for reading
02-20 10:53:19.303: D/OpenGLRenderer(5816): Enabling debug mode 0
02-20 10:53:19.373: D/memalloc(5816): /dev/pmem: Mapped buffer base:0x5db58000 size:3768320 offset:0 fd:67
02-20 10:53:20.143: W/dalvikvm(5816): threadid=11: thread exiting with uncaught exception (group=0x40abc210)
02-20 10:53:20.143: E/AndroidRuntime(5816): FATAL EXCEPTION: Thread-3102
02-20 10:53:20.143: E/AndroidRuntime(5816): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
02-20 10:53:20.143: E/AndroidRuntime(5816):     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4039)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at android.view.ViewRootImpl.invalidateChild(ViewRootImpl.java:722)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:771)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at android.view.ViewGroup.invalidateChild(ViewGroup.java:4112)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at android.view.View.invalidate(View.java:8639)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at android.view.View.invalidate(View.java:8590)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at android.widget.TextView.setGravity(TextView.java:2538)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at com.example.saikoro.MainActivity.title(MainActivity.java:58)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at com.example.saikoro.MainActivity$1.run(MainActivity.java:36)

回答1:

Change your startingUp() to this.

 private void startingUp() {
    Thread timer = new Thread() { //new thread         
        public void run() {
            Boolean b = true;
            try {
                do {
                    counter++;
                    title();
                    sleep(1000);

                    runOnUiThread(new Runnable() {  
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub

                        title.clearComposingText();
                    }
                });


                }
                while (b == true);
            } catch (IntruptedException e) {
                e.printStackTrace();
            }
            finally {
            }
        };
    };
    timer.start();
}

You can't modify views from non-UI thread.



回答2:

This exception is not coming due to title.clearComposingText(). even this line is not useful ,we can remove this line. This exception is coming in to title() function because a non UI-Thread is trying to modify view. so we need to call this function in a UI Thread or Handler.

private void startingUp() {
        Thread timer = new Thread() { //new thread         
            public void run() {
                boolean b = true;
                try {
                    do {
                        counter++;

                        sleep(1000);
                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                  title();
                                //title.clearComposingText();//not useful

                            }
                        });


                    }
                    while (b == true);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally {
                }
            };
        };
        timer.start();
    }


回答3:

You can't modify the text with title.clearComposingText(); inside the thread because you can only modify views from the UI thread. Use a handler instead and let him change the text.



回答4:

You should not update textView from thread other than UI thread.You can use asynctask for this.Can refer this



回答5:

As other people already stated, you cannot modify the UI from a background thread.

You can either use AsyncTask, or use the Activity.runOnUiThread() method