Android Compose LazyGrid重排视频瓦片时EGL_BAD_ACCESS错误排查
问题
使用Android Compose的LazyVerticalGrid展示视频网格,通过继承TextureView的自定义Renderer加载视频流。正常显示无问题,但重排视频瓦片(如交换首尾项)时,部分视频冻结、变绿,日志报错:
E/libEGL: eglMakeCurrentImpl:1038 error 3002 (EGL_BAD_ACCESS) E/Render: eglMakeCurrent failed E/Render: EGL error = 0x3002 E/Render: cannot swap buffers!
相关代码:
屏幕布局代码
LazyVerticalGrid( ... ) { items(items = members, key = { id }) { member -> val context = LocalContext.current AndroidView(factory = { Renderer(context, ...).apply { layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) } } }
自定义View代码
public class Renderer extends TextureView implements TextureView.SurfaceTextureListener { private SurfaceTexture mSurface; private EGLDisplay mEglDisplay; private EGLSurface mEglSurface; private EGLContext mEglContext; private EGL10 mEgl; private EGLConfig eglConfig; private GL10 mGl; ... //some code for creating the surface }
对OpenGL了解有限,求问引发EGL_BAD_ACCESS及缓冲区问题的原因。
原因分析
- EGL资源未正确释放与复用冲突:
LazyVerticalGrid的items使用key后,重排时会复用已有View实例而非重建,但自定义Renderer中的EGL资源(EGLDisplay、EGLSurface、EGLContext等)未在View复用前完成清理。当View被复用于新的视频流时,旧的EGL上下文仍绑定在当前线程,新的EGL操作尝试访问已失效或被占用的资源,触发EGL_BAD_ACCESS。 - SurfaceTexture生命周期未与View绑定:
TextureView的SurfaceTexture会在View被detach或复用时发生变化,但自定义Renderer可能未正确处理SurfaceTextureListener的回调(比如onSurfaceTextureDestroyed时未释放EGL资源)。重排时,旧的SurfaceTexture已失效,但EGL仍尝试向其交换缓冲区,导致冻结或绿屏。 - 线程安全问题:EGL操作(如
eglMakeCurrent、eglSwapBuffers)必须在创建EGL上下文的线程执行。如果视频渲染线程未与View的生命周期绑定,重排时View被切换到新的线程环境,或多个线程同时操作同一EGL资源,会引发资源访问冲突。 - EGL上下文未正确解绑:当View被复用时,若未先调用
eglMakeCurrent(null, null, null, null)解绑旧的EGL上下文,新的渲染操作尝试绑定新上下文时,会因旧上下文仍占用当前线程的EGL资源而报错。
内容的提问来源于stack exchange,提问作者Oussèma Hassine
相关产品推荐
相关产品推荐

