google / google/filament

ModelViewer + SurfaceView within a RecyclerView crash

Open
#4,724 8 comments 1 reaction 1 assignee Assigned to @pixelflinger View on GitHub
android
Dominant language
C++
Stars
20.5k
Forks
2.3k
Avg merge
2d 14h
Merged PRs (30d)
83

Description

**Describe the bug**
When attaching a `SurfaceView` to a `ModelViewer` within a `RecyclerView`, the view lifecycle isn't properly handled. A `SurfaceView` is detached from the window but not destroyed. When the `SurfaceHolder.Callback` attached within the `UiHelper` callbacks are invoked, the engine has been already been destroyed resulting in the provided stack trace.

**To Reproduce**
Steps to reproduce the behavior:
1. Put multiple `SurfaceView` backed by `ModelViewer` into a `RecyclerView`
2. Scroll up or down until a view is detached from the window, but not destroyed, then scroll back to that view

**Expected behavior**
Any cleanup/configuration (specifically with the engine) should be properly cleaned up/recreated when the view detaches/reattaches itself without relying on complete destruction/reconstruction of the view itself.

**Logs**
```
java.lang.IllegalStateException: Calling method on destroyed Engine
at com.google.android.filament.Engine.getNativeObject(Engine.java:649)
at com.google.android.filament.Engine.createSwapChain(Engine.java:293)
at com.google.android.filament.Engine.createSwapChain(Engine.java:271)
at com.google.android.filament.utils.ModelViewer$SurfaceCallback.onNativeWindowChanged(ModelViewer.kt:362)
at com.google.android.filament.android.UiHelper.createSwapChain(UiHelper.java:570)
at com.google.android.filament.android.UiHelper.access$100(UiHelper.java:120)
at com.google.android.filament.android.UiHelper$1.surfaceCreated(UiHelper.java:405)
at android.view.SurfaceView.updateSurface(SurfaceView.java:1173)
at android.view.SurfaceView.lambda$new$0$SurfaceView(SurfaceView.java:173)
at android.view.-$$Lambda$SurfaceView$w68OV7dB_zKVNsA-r0IrAUtyWas.onPreDraw(Unknown Source:2)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1093)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3096)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1959)
```

**Smartphone (please complete the following information):**
- Device: Sony Xperia 5ii
- OS: Android 11

**Additional context**
Right now it seems the only solution around this (while still using `ModelViewer`) is to force the `RecyclerView` to not recycle those views.
This is possible via
```
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.setIsRecyclable(false)
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.