从单独的线程调用requestLayout

时间:2014-06-24 17:30:22

标签: java android android-layout

我在GLSurfaceView.Renderer上有一个OpenGL游戏循环(更新+绘图),它运行在一个单独的线程上,而不是GLSurfaceView子类(包含渲染器)的线程。

有时,更新循环逻辑决定,"嗯,我们需要将视图调整为一半大小"。然后它调用GLSurfaceView视图的requestLayout,我的onMeasure函数将负责调整大小。

然而,事实证明我不应该从构成视图层次结构的原始线程以外的任何其他线程调用requestLayout。我得到以下例外:

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>

我尝试使用postInvalidate,但我认为我需要的是更接近postRequestLayout()的东西。但是,只有requestLayout()。

如何以某种方式触发requestLayout?

我不确定这是否会使事情变得复杂,但视图由输入法服务的任何运行所拥有。是的,它是一个基于OpenGL的Android键盘,但这是另一个可能与这个问题不太相关的长篇故事。

1 个答案:

答案 0 :(得分:1)

您需要post() Runnable对主线程进行任何与UI相关的操作。

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

请务必注意,您在run()方法中放入的代码不会立即完成。它被添加到主线程处理的队列中并将被执行&#34;有时&#34;在将来。