https://kotlinlang.org logo
#compose-android
Title
# compose-android
c

Colton Idle

06/01/2023, 9:04 AM
Funky issue I've got. I'm using
AndroidView
with a
SurfaceView
If I have an
if
statement to show/hide the AndroidView... it renders the first time, but if the if statement flips to false and true again, the AndroidView won't render. 🧵
Copy code
@Composable
fun MyAndroidView() {
  AndroidView(
      factory = { ctx ->
        SurfaceView(ctx).apply {
          Log.e("TEST", "apply")
          this.holder.addCallback(
              object : SurfaceHolder.Callback {
                override fun surfaceCreated(holder: SurfaceHolder) {
                  Log.e("TEST", "created")
                }

                override fun surfaceChanged(
                    holder: SurfaceHolder,
                    format: Int,
                    width: Int,
                    height: Int
                ) {
                  Log.e("TEST", "changed")
                }

                override fun surfaceDestroyed(holder: SurfaceHolder) {
                  Log.e("TEST", "destroyed")
                }
              })
        }
      })

}
The logs I get initially:
Copy code
apply
created
changed
changed
then when my if statement flips to false
Copy code
destroyed
then when it flips back to true
Copy code
apply
Why doesn't it get created?!?
At that point if I press a button (like press it down and don't release it) it will go ahead and do
Copy code
created
changed
changed
Something just feels wrong here
j

Joel Denke

06/01/2023, 4:23 PM
I think you want to move apply block after Surface View to AndroidView setup method. Factory only called once upon creation I think. Setup block called each recomposition.
See sample at https://developer.android.com/jetpack/compose/migrate/interoperability-apis/views-in-compose Argument called update what I referred to as setup.
For callback I also think potentially need rememberupdated and store outside AndroidView to remember it not recreated each time view recomposition or inflates.
c

Colton Idle

06/01/2023, 5:08 PM
Interesting point with remember of the callback. I guess I can try that.
j

Joel Denke

06/01/2023, 5:11 PM
Its a little complicated how compose evaluates lambda expressions if they refer to stateful compose states. You want updating lambda when that happens but keep lambda itself. Helped me a lot of times but also confusing me. Potentially solves part of your issue. As I dont know rest of code not sure.
c

Colton Idle

06/01/2023, 5:16 PM
Yeah. when im back at my desk i will give this a try
j

Joel Denke

06/01/2023, 5:18 PM
Also can be bugs under hood. Mixing AndeoidView interop not always play nice, like nested scrolling in Webview. Could be some ui frame updating in SurfaceView behaves different. But I am no expert :) I just avoid AndroidView in compose as much as possible.
c

Colton Idle

06/01/2023, 8:16 PM
Yep. I wish I could avoid it here.
25 Views