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

Uli Bubenheimer

05/26/2022, 7:11 PM
I would like to optimize this function somehow: it emits a sequence of composables after applying a sequence of modifiers:
Copy code
@Composable
fun ModifiedRow(
    modifier: Modifier,
    columnModifiers: StableImmutableList<Modifier>,
    vararg columns: @Composable (Modifier) -> Unit
) = Row(modifier) {
    val composableIter: Iterator<(Modifier) -> Unit> = columns.iterator()

    columnModifiers.forEach(composableIter.next()::invoke)
}
The Rows are emitted inside a LazyColumn, so I'd like this to be better performing. I want to use this to align header column widths with data column widths. What I would like to see is inlining all these composables so that they don't get their own recompose scopes, they're all simple lambdas emitting a single Composable each. I could manually unroll the vararg, since I use this for exactly 15 columns right now, but I'm holding out for something more elegant. I'm guessing that some advanced Compose magic could pull this off (even though it may be overkill compared to the manual unroll approach).
l

Leland Richardson [G]

05/26/2022, 7:15 PM
can you elaborate more on the use case or show what you are doing at the call site? it’s not clear to me what this is adding
u

Uli Bubenheimer

05/26/2022, 7:23 PM
Essentially this, aligning header columns widths with data column widths:
Copy code
LazyColumn {
    stickyHeader {
        Row {
            Text("A", Modifier.width(10.dp))
            Text("B", Modifier.width(13.dp))
            // ...
            Text("Z"), Modifier.width(7.dp)
        }
    }

    items(pagingItems) {
        Row {
            Image(it.a, Modifier.width(10.dp))
            Text(it.b, Modifier.width(13.dp))
            // ...
            Switch(it.z, Modifier.width(7.dp))
        }
    }
}
I only want to specify the widths once, and don't want to keep the widths manually aligned, because that's pretty error-prone with a large number of columns (with or without additional constants).
l

Leland Richardson [G]

05/26/2022, 7:33 PM
not sure if this is a silly idea but can you not just define the modifiers above these scopes once and then just use the reference to them in the header/items rows?
and can you show me how the OP code would be used in the above code?
u

Uli Bubenheimer

05/26/2022, 7:37 PM
That's easy to validate when you have a handful of columns but this kind of approach gets unwieldy with 15 columns, it's hard to verify the correctness, as you still have to reference your 15 modifier variables 30 times, twice each in the correct places
You also have to define them correctly first, and the definitions are now completely removed from the usage sites
l

Leland Richardson [G]

05/26/2022, 7:38 PM
(to be clear, not saying your idea is unwarranted, just wanting to make sure i understand the problem you are solving)
u

Uli Bubenheimer

05/26/2022, 7:43 PM
I guess I can't get around defining the modifiers separately though. I had filed this feature request to get something that does not have this problem, but it was turned down: https://issuetracker.google.com/issues/200059826
What I'd really like to have is to define my column widths with my headers, then it's all clean and easy to understand and validate. Everything else just turns into a freakin' mess
Like I say in that feature request, displaying a data table with equally aligned header & body columns is a standard use case in pretty much all UIs and should be supported by Compose UI. Of course, that's not what you deal with I believe
l

Leland Richardson [G]

05/26/2022, 7:47 PM
i think your use case is a table layout which LazyColumn isn’t really meant to be. i think the best thing would be for someone (you, someone else, google, or whoever) to make a proper table layout composable that would accomodate this use case in the API shape as well as in the guarantees of the layout algorithm, both of which lazy column does not currently do
u

Uli Bubenheimer

05/26/2022, 7:48 PM
Yes, that makes sense. I saw some Lazy-related changes in recent compose alphas where I thought it might possibly go in this direction, but have not looked into it. Probably not, based on the outcome of the feature request.
Still, I think I can address this a little better with the gist that I posted initially, but would like a better performing version, plus it would be interesting for me to see what Compose magic I might use here.
I've started unrolling my vararg...
I guess I could instead use a lookup
Map<String, Modifier>
for the widths, which would make it easier to validate their correct usage sites.
But really using constants is better, so I guess that's what I'll do after all.
Thanks for forcing me to think it through!
👍 2