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

Manuel Wrage

06/08/2020, 8:28 AM
Are there any examples of using Dagger with Compose?
g

gildor

06/08/2020, 8:30 AM
Isn’t Dagger and Compose are indifferent to each other?
m

Manuel Wrage

06/08/2020, 8:34 AM
I mean something like injecting dependencies inside a @Composable or using injected classes which itself have @Composable functions inside @Composable's
g

gildor

06/08/2020, 8:40 AM
I’m not sure that it’s right approach in general But probably it’s possible to inject a class which has composable functions
inject a top level function not what you can do tho
a

Adrian Blanco

06/08/2020, 10:41 AM
I've made some small experimentations with having a tree of nodes, where each node exposes a composable view and has their dependencies injected with Dagger. So a bit inspired by RIBs https://github.com/adrianblancode/Cheddar
m

Manuel Wrage

06/08/2020, 9:25 PM
@Adrian Blanco interesting approach. This is something like what i was looking for.
After giving it some thought i came up with a slightly different and more basic approach. It's inspired by UseCases with a single suspend invoke function. Just a plain class with a single @Composable function. This way i can easily inject stuff and, in case i need todo some work while the ui is displayed i can use a view model which is tight to the the context of the composition. It should be also very easy to test it.
class UserList @Inject constructor(
private val viewModelFactory: Provider<UserViewModel>
) {
@Composable
operator fun invoke() {
val viewModel = remember { viewModelFactory() }
AdapterList(data = viewModel.state.collectAsState().items) { user ->
User(user = user, onClick = { viewModel.userClicked() })
}
}
}
What do you think about it?
a

Adrian Blanco

06/09/2020, 12:50 PM
I think it's an interesting architectural solution to instead of wrapping per logical node to wrap per view, because then you can also keep DI and views separate. I mostly wrote mine as a complete replacement for fragments and backstacks and such, so might have missed some context. I think the hard problems would be about composition and nesting. For example a regular compose view would not be able to just call a wrapped view, so by necessity it might require a lot of wrapping or tying things to local variables. Then there is the question of passing eg event listeners or IDs through the hierarchy, which could require @Assisted injection of sorts, and that type of boilerplate is always a bit hard to manage. Another problem might be lifecycles. Having Provider<VM> might cause issues with passing the same VM if you have eg a list of the same wrapped view. Then it's also the question of when onCleared will be called in the VM, because the composition will dispose collectAsState() properly but it might not prevent work from still being performed in the VM with eg viewModelScope long after the compose view itself is no longer in use. But yeah scaling up is always hard and there's a million ways to do it, and that's why I hope Google will be able to come up with some cool solutions :p