Written as of alpha09. Compose is evolving rapidly so some syntax may have changed.
In part 1 I took a look at how lists work in Jetpack Compose — the new UI framework for Android. Now I’m going to take a look at how these list elements come together in reality with a simple todo list.
Because of the data driven approach of Jetpack Compose, architecture patterns which rely on returning a listenable stream of data to the view work quite well. For this sample I’ll use and MVI style pattern.
Listening to the ViewState
For now lets rely on Activity/Fragments to act as navigable UI containers. There is a more compose way of doing things with the new navigation-compose library but we’ll keep things familiar by only having compose replace xml files.
Here our activity handles creating the view model and passing it to the first composable (you could equally use a favoured DI framework). Then in the
TodoScreen the list can be created, any view state can be listened to, and state/actions can be passed to further composables through the hoisting pattern common in compose.
As shown in the previous article, creating the list is super simple.
There are a couple of useful bits to go into here.
contentPadding = paddingValues(16.dp, 16.dp)
Content padding lets us add padding to the top and bottom (and/or gutters) of the list. Think of the fiddly way of adding of bottom spacing in
RecyclerView with item decorators — compose makes the process miles simpler and less error prone.
verticalArrangement = Arrangement.spacedBy(8.dp)
Vertical arrangement gives a top level way of adding item spacing — really useful when quickly creating simple lists.
Where this simple vertical arrangement can fall down is when creating complex multi-item lists which may require different spacing between different item types. Perhaps in complex lists it’d be useful to wrap items in a ’decorator’ composable, to use
RecyclerView lingo. This would also let you customise other attributes like gutters per item type or index.
Overall it seems fairly easy to replace lots of the behaviour of
ItemDecorations with simpler compose functionality.
Now we need a way to hook up clicks on a checkbox to our view model.
This ends up working super simply. The hoisted action can be called using the todo state originally passed to the composable.
Every time the actions called, the view model rebuilds it’s view state, and sends the new state back to the top of the compose tree.
This data driven approach gives a lot of simplicity. It lets composables at the bottom of the tree update composables nearer the top with very little boiler plate. And because the compose innards only trigger composable updates on state changes, you can be safe in the knowledge that this is an inexpensive operation in terms of performance.
RecyclerViewhas a stack of animation libraries around it to enable slick lists, there isn’t yet that ecosystem in compose, but Rasul gives a good intro into how these could be implemented here.
- Filtering would be quite easy to achieve with a similar setup to above, send a filter action to the view model, rebuild the list, and emit the new list as a view state.
- Multi-selection could also be achieved with a similar setup.
- There seems to be no way to implement dragging at the moment, although if you can think of something creative, stick in a comment!
Happy composing :)
For full samples see the repo here