https://kotlinlang.org logo
m

Mark Murphy

05/27/2020, 9:39 PM
In
dev11
, you could call a top-level composable function from a library via reflection by passing in
currentComposer
:
Copy code
val clazz = Class.forName("com.commonsware.jetc.specimen.basics.ActionCheckboxKt")
val demoMethod = clazz.methods.find { it.name == "ActionCheckboxDemo" }

demoMethod?.let {
    it.isAccessible = true
    it.invoke(null, currentComposer)
}
In this case,
ActionCheckboxDemo()
has zero parameters in terms of the way the source is written. But, if you looked at the compiled class file (e.g., via External Libraries in Studio), you would see that the function was rewritten to take a
Composer
. I'm uncertain how to accomplish this in
dev12
. If I look at the compiled class file, it claims to take zero parameters. If I try
invoke()
, it claims to take 3 parameters. The release notes support the three-parameter signature, though the docs seem to be somewhat mangled:
A Composable function accepting a single parameter is transformed into a function accepting 3 parameters, the additional parameters are the Composer, a ‘key’ integer. a bitmask integer used to propagate metadata through calls.
If I change the invocation to
it.invoke(null, currentComposer, 0, 0)
, it runs. But... should I be deriving better values for those integers from somewhere?
l

Leland Richardson [G]

05/27/2020, 10:32 PM
unfortunately it is not as easy to do this now. I would like us to consider exposing some reflection extension methods as public API that would allow people to do this safely. You can find the equivalent code here: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/PreviewUtils.kt;l=100?q=previewutils.kt
the number of synthetic a composable function has depends on a few things
and will change over time. namely, the
key
parameter will be going away soon. we had to add it in in order to preserve backwards compatibility with some tooling, but right now it isn’t strictly necessary for the runtime itself
so roughly speaking, a composable function will have: 1 composer paramter 1 key parameter (for now) 1 “changed” parameter (per every 15 formal parameters) 1 “defaults” parameter (per every 31 formal parameters) if there are any default expressions in the declaration
😮 2
(and passing
0
for the changed and default parameters will always be a reasonable value to pass)
m

Mark Murphy

05/27/2020, 10:39 PM
You can find the equivalent code here:
Yeah, I figured you had to have some mechanism for this for the
@Preview
support.
I would like us to consider exposing some reflection extension methods as public API that would allow people to do this safely.
Developers wanting to invoke composables via reflection is inevitable. Kinda like Thanos. So, having some first-class way of doing it, rather than schlubs like me cobbling together stuff that works but not always, seems like A Really Good Thing.
l

Leland Richardson [G]

05/27/2020, 10:40 PM
yeah, I agree
it’s also important to enable “server side rendering” type stuff that people will certainly want to do
m

Mark Murphy

05/27/2020, 10:42 PM
any value in my filing an issue for this? I don't know how much use the team gets from feature request issues vs. bug reports
l

Leland Richardson [G]

05/27/2020, 10:43 PM
if you’re willing to, then by all means, please do. i think whenever a user files a bug/feature request it sends a strong signal about external desire (at least it does from my POV)
👍 1
m

Mark Murphy

05/27/2020, 10:53 PM
I've filed 768 so far. Another one won't hurt: https://issuetracker.google.com/issues/157590194
😂 4