简体   繁体   中英

Android: only the original thread that created a view hierarchy can touch its views when calling invalidate()

I'm trying to play a gif using the Movie object and it requires me to call the invalidate() method. However whenever I call this method I get the following error:

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

How do I fix this and why is it happening

Runs the specified action on the UI thread.

I would like to recommend read this site runOnUiThread

runOnUiThread(new Runnable() {
  @Override
  public void run() {
    // call the invalidate()
  }
});

try this

 final Handler handler=new Handler();
    new Thread(new Runnable() {
        @Override
        public void run() {
           //your code
            handler.post(new Runnable() {
                @Override
                public void run() {
                    invalidate()
                }
            });
        }
    }).start();

In Android, only the Main thread (also called the UI thread) can update views. This is because in Android the UI toolkit s not thread safe.

When you try to update the UI from a worker thread Android throws this exception.

Make sure to update the UI from the Main thread.

in case you need it in Kotlin:

val handler = Handler(Looper.getMainLooper())
    handler.post({
        invalidate()
    })

There's actually a method in the Android SDK you can use to run invalidate() on the UI thread without having to make your own runnable or handler manually, see the official docs here .

public void postInvalidate ()

Cause an invalidate to happen on a subsequent cycle through the event loop. Use this to invalidate the View from a non-UI thread.

This method can be invoked from outside of the UI thread only when this View is attached to a window.

I know this is an older question and the answers here already work but I had an issue with just using Handler because by default android studio uses the wrong Handler object. I had to specify android.os.Handler ie:

final android.os.Handler handler=new android.os.Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            do_your_ui_stuff_here
            }
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM