Thread
#compose
    m

    Mark Murphy

    2 years ago
    In
    dev11
    , you could call a top-level composable function from a library via reflection by passing in
    currentComposer
    :
    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]

    2 years ago
    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
    (and passing
    0
    for the changed and default parameters will always be a reasonable value to pass)
    m

    Mark Murphy

    2 years ago
    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]

    2 years ago
    yeah, I agree
    it’s also important to enable “server side rendering” type stuff that people will certainly want to do
    m

    Mark Murphy

    2 years ago
    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]

    2 years ago
    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)
    m

    Mark Murphy

    2 years ago
    I've filed 768 so far. Another one won't hurt: https://issuetracker.google.com/issues/157590194