1

I have an OpenGL game loop (update+draw) on a GLSurfaceView.Renderer that runs on a separate thread than the thread that the GLSurfaceView subclass (which contains the renderer) was made.

Sometimes, the update loop logic decides, "Hmm, we need to resize the view to half size". It then calls the GLSurfaceView view's requestLayout, and my onMeasure function would take care of the resizing.

However, it turns out I'm not supposed to call requestLayout from any other thread other than the original thread that made the view hierarchy. I got the following exception:

E/AndroidRuntime( 3693): FATAL EXCEPTION: GLThread 3424
E/AndroidRuntime( 3693): Process: com.android.gl2jni, PID: 3693
E/AndroidRuntime( 3693): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
E/AndroidRuntime( 3693):        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
E/AndroidRuntime( 3693):        at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:857)
E/AndroidRuntime( 3693):        at android.view.ViewGroup.invalidateChild(ViewGroup.java:4320)
E/AndroidRuntime( 3693):        at android.view.View.invalidate(View.java:10935)

<snip>

I tried using postInvalidate, but I think what I need is something closer to postRequestLayout(). However, there's only requestLayout().

How do I trigger requestLayout, somehow?

I'm not sure if this complicates things, but the view is owned by whatever runs the Input Method Service. Yep, it's an OpenGL based android keyboard, but that's another long story that might not be too relevant to this issue.

kamziro
  • 7,882
  • 9
  • 55
  • 78

1 Answers1

1

You need to post() a Runnable with any UI-related actions to the main thread.

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        // do UI work
        yourview.requestLayout();
    }
});

It's important to note that the code you put inside that run() method will not complete immediately. It gets added to a queue that the main thread processes and will get executed "sometime" in the future.

tophyr
  • 1,658
  • 14
  • 20