Hello, if anyone wants/needs to use `RecyclerView`...
# compose-wear
l
Hello, if anyone wants/needs to use
RecyclerView
or
WearableRecyclerView
in a
@Composable
function, you need to hack around to get rotary input to work. If any of you need that, let me know, I will share my code in a gist or in an open source library. BTW, does anyone know how to have something like
ScalingLazyColumn
but with
RecyclerView
? Basically, I'm looking for the same effect as in the Settings app and in the App Drawer from the Pixel Watch.
j
Thee simple answer is to use the ScalingLazyColumn. We do not have a RecyclerView/WearableRecyclerView with scaling and fading and will not be adding one as Kotlin/Compose is our recommended API.
All of our UI efforts are focused on Kotlin and Compose. Is there a reason you can not use Compose for your use case?
l
Performance is the problem, both for debug and release. RecyclerView doesn't ditch Views (aka
AndroidView
) as soon as they exit the screen, and when you have Views that are a bit expensive to instantiate, that makes a huge difference. With RecyclerView, it barely lags. With LazyColumn and ScalingLazyColumn, you get dropped frames all the time because it keeps recreating
AndroidView
elements, and it's not recycling them of course.
What I have in a View, I cannot easily make it native to Compose, I don't have the time to yet at least as I need to release a beta in the next 6 days, and a stable release before the Holiday season, with all the marketing work that I also need to do myself.
Are the App Drawer and the Settings app using
ScalingLazyColumn
themselves? I really doubt it since you get the haptic feedback on rotary input that you currently only get when linked to a
RecyclerView
.
I wish Wear OS was open source, I'd have been able to look at how it's implemented.
y
I wonder whether you can implement the pooling yourself in some ScalingLazyViewColumn wrapper? AndroidView is completely open to how you create the views, so you could do the pooling yourself.
l
AndroidView
isn't that open actually, it's a pain to work with beyond the make this View composable use case.
j
We are working on adding device independent rotary and haptics support to AndroidX - but it takes time as we need the right APIs in place. We have added improved rotary support into Horologist recently and will be continuing to improve RSB and Haptics support there including device specifics if needed - @Michail Kulaga FYI
l
For a screen where I had only one View to display among a list of other composables, I tried to create the view, and inject it in the
factory
parameter passed to
AndroidView
, but then I got errors like "this view already has a parent". Then I tried to remove it, but got other errors, after spending too much time on it, I gave up, tried my Compose RecyclerView wrappers, and I saw it was smoother, even when it only contains Composables, and especially in debug mode, so I only use that now.
So there you go, 2-3 good reasons to stick with RecyclerView for now. Do any of you know what's used in the Pixel Watch scrollable menus I mentioned? Some special
RecyclerView
, some
ListView
,
ScalingLazyColumn
, or some add-on on top of the 2 former things I mentioned?
j
The PixelWatch style scrollable menus are all trivial to implement in Compose - Settings and prefs was the first sample demo I implemented. Personally I would stick to views or compose and not mix and match between ScalingLazyColumn and Views and RecyclerView and composables. And if you want the scaling and fading then ScalingLazyColumn is there for you.
y
A RecyclerView with custom maths and animation for scaling child views. That won't be public API. And every OEM can do slightly different.
Although while they started out the same, the ScalingLazyColumn is the way forward, and getting material tweaks etc. So I hope the answer is find ways to either use compose only, or perhaps fix the issues you faced with pooling and AndroidViews.
l
@John Nichol Is that answering what the Pixel Watch menus are actually using themselves?
It feels like you're trying to convince me to use
ScalingLazyColumn
, even though it's not working well for me at the moment. I guess I'll give up the scaling animations for now…
j
Happy to work with you to understand why they are not working for you. We have a lot of apps using them very successfully
l
I think I already said why in this thread.
I'll write it again: 1. Compose doesn't recycle views created by
AndroidView
, so you get frame drops every time a Composable that includes one comes back into the screen. 2.
ScalingLazyColumn
and
LazyColumn
is always insanely laggy in debug to the point that it's just unsuable, with or without
AndroidView
. On the other hand
RecyclerView
and
WearableRecyclerView
(the screen curvature following one), even with `ComposeView`s all inside, and even when it's also inside a composition, is usable, and can be smooth. 3.
RecyclerView
and friends are the only ones that provide the nice haptics when using rotary input now.
I cannot afford to skip the debug variant because, well, I need to debug my app.
But I cannot test my debug app to find bugs if it's so slow.
y
ScalingLazyColumn can support haptics if you use Modifier.rotaryWithSnap() from Horologist 0.2.3
l
Good to know, only 2 reasons left to stick to RecyclerView. Might give it a go for future simpler apps where I don't need as much debugging.
y
I took a stab at custom recycling with SLC + AndroidView. Assuming some View (CustomTextView) that we want to recycle. And then using a pool aware wrapper for ScalingLazyColumn and a wrapper for AndroidView (TextViewComposable) that uses the pool as the factory. Seems to work ok, but I haven't benchmarked it. https://github.com/yschimke/horologist/commit/46ebd24c0fd527493638c7b76c4f9384c8e83bee
l
I must admit I thought a bit about this approach but hadn't tried. Will try it later to see how it works for me. Thank you!
y
I suspect you could delete the ViewPool and replace it with RecycledViewPool but I don't want to battle this complexity. This was mainly a POC and to discuss any issues with the approach. It's the second time we've had to investigate performance issues with view inflation inside SLC.
I can't solve the debuggability of SLC and Compose in general on devices with debug builds. It's a known issue with no clear solution. And acutely painful on Wear specifically, compared to mobile.
l
I think I could help with that as I mimmicked the API of SLC & LazyColumn in my
RecyclerView
composable wrappers. There are some missing parts because I didn't need them yet, but I think it would be possible to bridge the gap
y
Follow along on 1) at b/230099236