https://kotlinlang.org logo
#compose
Title
# compose
k

Kevin Hester

03/11/2020, 10:26 PM
dear composegeeks. Is https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:ui/ui-android-view/src/main/java/androidx/ui/androidview/ComposedView.kt still the best example on how to put an android view underneath a Compose component? When I tried using it I get: java.lang.IllegalStateException: Could not convert androidx.ui.androidview.AndroidViewHolder to an Emittable at androidx.compose.ViewApplyAdapter.end(ViewComposer.kt:119) at androidx.compose.Applier.up(Applier.kt:51) at androidx.compose.Composer$realizeSlots$12.invoke(Composer.kt:1377) ... at androidx.ui.material.DrawerKt.ModalDrawerLayout(Drawer.kt:113) at com.geeksville.mesh.ui.MeshAppKt$MeshApp$2.invoke(MeshApp.kt:160) at com.geeksville.mesh.ui.MeshAppKt$MeshApp$2.invoke(Unknown Source:3) at androidx.compose.AmbientKt.Providers(Ambient.kt:176) at androidx.ui.core.TextKt.CurrentTextStyleProvider(Text.kt:386) at androidx.ui.material.MaterialThemeKt$MaterialTheme$1$invoke$1.invoke(MaterialTheme.kt:92) at androidx.ui.material.MaterialThemeKt$MaterialTheme$1$invoke$1.invoke(Unknown Source:3) at androidx.compose.AmbientKt.Providers(Ambient.kt:176) at androidx.ui.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:92) at androidx.ui.material.MaterialThemeKt$MaterialTheme$1.invoke(Unknown Source:3) at androidx.compose.AmbientKt.Providers(Ambient.kt:176) at androidx.ui.material.ColorKt.ProvideColorPalette(Color.kt:328) at androidx.ui.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:92) at androidx.ui.material.MaterialThemeKt.MaterialTheme$default(MaterialTheme.kt:43) at com.geeksville.mesh.ui.MeshAppKt.MeshApp(MeshApp.kt:201) at com.geeksville.mesh.ui.MeshAppKt$MeshApp$5.invoke(Unknown Source:0) at com.geeksville.mesh.ui.MeshAppKt$MeshApp$5.invoke(Unknown Source:3) at androidx.compose.RecomposeScope.compose(Composer.kt:208) at androidx.compose.Composer.composeScope(Composer.kt:1239) at androidx.compose.Composer.recomposeComponentRange(Composer.kt:1185) at androidx.compose.Composer.skipCurrentGroup(Composer.kt:1234) at androidx.compose.Composer.recompose(Composer.kt:1303) at androidx.compose.Recomposer.performRecompose(Recomposer.kt:93) at androidx.compose.Recomposer.dispatchRecomposes(Recomposer.kt:119) at androidx.compose.AndroidRecomposer.access$dispatchRecomposes$1(Unknown Source:0) at androidx.compose.AndroidRecomposer$frameCallback$1.doFrame(AndroidRecomposer.kt:27) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:964) at android.view.Choreographer.doCallbacks(Choreographer.java:790) at android.view.Choreographer.doFrame(Choreographer.java:721)
this is with dev-06 btw
l

Leland Richardson [G]

03/11/2020, 10:28 PM
a lot of this is getting reworked right now. a lot is possible currently but it’s a bit fragile and confusing. what are you trying to do? i can probably point help you get things working
k

Kevin Hester

03/11/2020, 10:30 PM
I'd like to host a MapBox view anywhere under my compose hierarchy. Something very similar to step 4 of this: https://docs.mapbox.com/android/maps/overview/
thanks for your repeated assistance btw!
my xml was literally just this:
Copy code
<com.mapbox.mapboxsdk.maps.MapView
  android:id="@+id/mapView"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  />
I'd be okay with also not using xml and just making the view directly from kotlin if there was a way to do that
i.e. (newing the view and passing in a context)
my kotlin code was just:
Copy code
@Composable
fun MapContent() {
    analyticsScreen(name = "map")

    val typography = MaterialTheme.typography()
    val context = ContextAmbient.current

    AndroidView(R.layout.map_view) {
        
    }
}
l

Leland Richardson [G]

03/11/2020, 10:35 PM
how/where are you calling MapContent?
k

Kevin Hester

03/11/2020, 10:36 PM
essentially here: https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt#L145 (though the new line that uses MapContent instead of ChannelContent etc... is not yet pushed to github)
l

Leland Richardson [G]

03/11/2020, 10:41 PM
hmm
a lot of these code paths have changed since dev06 so i’m trying to figure out what exactly is happening here. i’d think what your doing would work. the exception seems to indicate that it is getting down the wrong code path but i can’t thnk of why that would be
can you try something that sounds kinda dumb but might work
wrap MapContent in a
Column
and see what happens
k

Kevin Hester

03/11/2020, 10:47 PM
trying that!
alas no joy.
same behavior
r

romainguy

03/11/2020, 10:51 PM
Do you know if the MapBox view is a SurfaceView btw?
I don’t know how good support for SV is, it’s just a tad different than other views so this may be an issue
l

Leland Richardson [G]

03/11/2020, 10:51 PM
how are you starting off compose? can you link me to your call to
setContent
or similar?
@romainguy alas - no idea, but I wouldn't be surprised if it was, their website shows all sorts of fancy graphics options.
l

Leland Richardson [G]

03/11/2020, 11:02 PM
can you try and open this file in studio and set a breakpoint here, to verify that this line is getting called? and if so, it seems like this function is returning null when it shouldn’t be. https://android.googlesource.com/platform/frameworks/support/+/refs/changes/12/1243712/3/ui/ui-framework/src/main/java/androidx/ui/core/AndroidViewCompat.kt#30
in particular, this should get called from here. it might also be skipping over this entirely and going directly to the error if adapters is null: https://android.googlesource.com/platform/frameworks/support/+/refs/changes/12/1243712/3/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ViewComposer.kt#118
would be helpful to understand which one of those two scenarios is happening for you
k

Kevin Hester

03/11/2020, 11:04 PM
sure - trying now
hmm. it seems the reason a null is returned in ViewComposer.kt is that:
Copy code
class ViewAdapters {
    private val adapters = mutableListOf<(parent: Any, child: Any) -> Any?>()

    fun register(adapter: (parent: Any, child: Any) -> Any?) = adapters.add(adapter)
    fun adapt(parent: Any, child: Any): Any? =
        adapters.map { it(parent, child) }.filterNotNull().firstOrNull()
}
adapters in this class is empty
does that help?
(so I don't think it ever tried calling the code at line 30 of AndroidViewCompat
l

Leland Richardson [G]

03/11/2020, 11:09 PM
yeah that helps
k

Kevin Hester

03/11/2020, 11:09 PM
i.e. ViewAdapters.adapt used its OrNull to return null
l

Leland Richardson [G]

03/11/2020, 11:10 PM
k

Kevin Hester

03/11/2020, 11:10 PM
and to be clear, I assumed I was supposed to use ComposedView.kt as an example that I pulled into my own source? Is that actually in the compose tree now?
l

Leland Richardson [G]

03/11/2020, 11:11 PM
oh
hmm
because we aren’t publishing the ui-android-view module?
k

Kevin Hester

03/11/2020, 11:12 PM
yeah
l

Leland Richardson [G]

03/11/2020, 11:12 PM
that could be part of the problem
it’s not clear to me if a user-land version of it will work or not. it might
well actually
all of this is irrelevant if the adapter isn’t being used
so that’s our first problem
k

Kevin Hester

03/11/2020, 11:13 PM
k
I'll step through setContent and take a look
ok - I don't understand the magic of what remember{} is supposed to do here:
Copy code
private fun doSetContent(
    composeView: AndroidComposeView,
    context: Context,
    content: @Composable() () -> Unit
): Composition = Compose.composeInto(composeView.root, context) {
    val currentComposer = currentComposer as ViewComposer
    remember { currentComposer.adapters?.register(AndroidViewAdapter) }
    WrapWithAmbients(composeView, context, Dispatchers.Main) {
        WrapWithSelectionContainer(content)
    }
}
but, I can see that adapters != null but my breakpoint on ViewAdapters.register() never got hit
so perhaps something wrong with that? (because register was supposed to do adapters.add
I can step through remember more rigorously if it would help ya'll.
l

Leland Richardson [G]

03/11/2020, 11:23 PM
remember is just causing that register call to get called on first composition, but not after that
k

Kevin Hester

03/11/2020, 11:24 PM
ok - for my app, it seems it never got called
l

Leland Richardson [G]

03/11/2020, 11:24 PM
huh
k

Kevin Hester

03/11/2020, 11:31 PM
ok - i'm stepping through remember stuff
oops - I'll have to continue this investigation a bit later. I just did the auto update to 4.1 Canary 2 and I think it is a sick canary so I'll have to rollback.
(unrelated to this problem though)
l

Leland Richardson [G]

03/11/2020, 11:41 PM
lol
sick canary
k

Kevin Hester

03/11/2020, 11:42 PM
heh
i also need to go walk my cat, but will update in a few hrs
🐈 1
j

jolo

03/12/2020, 8:09 AM
are you and your cat ok? 😆
😂 4
k

Kevin Hester

03/12/2020, 4:48 PM
alas, walking the cat turned into dinner and drinking beer with peoples 😉. I need to finish up some other work items today/tomorrow but will return to the mapview experiment (and update this thread with findings) Saturday ish. 😉
🍻 2
🐈 2