Thread
#compose
    Robert Menke

    Robert Menke

    2 years ago
    Apologize if this has been asked a million times. Is it common to use dependency injection with something like Hilt with Compose? In @Leland Richardson [G]’s example in “Thinking in Compose” it looks like compose already has a helper function called
    viewModel
    that will provide a properly scoped view model. This looks great, but my concern is that for testing purposes if I want to create a fake for a service that makes a network call and then inject it into my view model I still need something like Hilt. Is there a recommended best practice or tutorial for dependency injection with compose?
    Ray Ryan

    Ray Ryan

    2 years ago
    I haven’t really been Composing yet, but it seems to me you should be able to inject things that provide @Composable functions. And that it would be very wise to resist the urge to abuse Ambients instead.
    satyan

    satyan

    2 years ago
    Technically, you will also tend to inject stuff in your top-level composable, the one that are going to be stateful and will require to do some work (such work should be kept minimal and delegated as much as possible to a view model). So I would argue that you can handle injection by passing things as composable function arguments 🤷
    Robert Menke

    Robert Menke

    2 years ago
    That would mean your top level composable would have to accept every view model in your entire application though which doesn’t seem like a great solution. I do see in JetCaster there’s an example of a dependency graph here https://github.com/android/compose-samples/blob/master/Jetcaster/app/src/main/java/com/example/jetcaster/Graph.kt.
    but I don’t think there’s any way to do field injection inside of a function with hilt, so I’m not sure how to proceed 🤔 .
    Ian Arbuckle

    Ian Arbuckle

    2 years ago
    Why would be it useful to inject dependencies to Composable functions? Aren't they better best left as stateless and driven from the outside i.e. view model.
    Robert Menke

    Robert Menke

    2 years ago
    The current approach to loading view models won’t allow you to use hilt’s DI system AFAIK, so injecting something like an outside service into your viewmodel via hilt wouldn’t work properly if I understand correctly.
    Ian Arbuckle

    Ian Arbuckle

    2 years ago
    I used Hilt with Compose and found no issues. I've only passed in a view model to my top level Composable function. https://github.com/IanArb/RickMortyComposeSample/blob/master/app/src/main/java/com/ianarbuckle/rickmortycompose/HomeActivity.kt
    Robert Menke

    Robert Menke

    2 years ago
    But if you had an application with a lot of view models you would have had to pass in every view model to your top level composable, no?
    Ian Arbuckle

    Ian Arbuckle

    2 years ago
    You can pass it to any Composable given it is injected from an activity/fragment. But yeah, if you are doing single activity approach, the activity would end up injecting too many view models. It's still early days and I'm sure Google are aware of architectural limitations
    Robert Menke

    Robert Menke

    2 years ago
    It seems like it’s a reasonable goal to use composable functions for an entire application without resorting to multiple activities. DI is one of the benefits of SwiftUIs approach of using structs for its views and I’ve been able to build a SwiftUI app using DI (with resolver) and it works well. I love that compose simplifies things down to just using composable functions, but it does seem like DI (and therefore e2e testing) is still currently a deficiency. Please don’t get me wrong I couldn’t be more excited about compose. It’s an incredible innovation in UI. I just want to use best practices for testing my app while building with compose.
    Ray Ryan

    Ray Ryan

    2 years ago
    Single Activity or Die
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    2 years ago
    I don’t think our DI instincts from classic Android development are necessarily directly applicable to Compose, at least not in the same way. https://kotlinlang.slack.com/archives/CJLTWPH7S/p1594385570100600?thread_ts=1594338382.091800&cid=CJLTWPH7S Also, as @Ray Ryan pointed out, if you really want to make a class that injects stuff and has a composable method, you can do that too.
    satyan

    satyan

    2 years ago
    @Zach Klippenstein (he/him) [MOD] the only place nail I would want to put a nail on is the view model from jetpack. View model (jetpacks ones) provides several benefits:- a boundary between UI and business logic - a scope (if I'm loading article on screen A and the user go back or elsewhere I want to stop loading or at least ignore the result) - saving state (configuration change) Being boundaries to the business logic, you need to inject business logic in the view model (use cases or repositories). If you need to inject business logic in a view model you need to be able to inject a view model factory (manual one or using assisted inject) in screens. You could create classes for those screens to inject the view model factory (plus formatters, trackers, loggers, ...). If you only have callbacks and pure data in composable functions you will require to handle manually those three concerns (which isn't a bad or good thing 🤷‍♀️).
    Robert Menke

    Robert Menke

    2 years ago
    So to be clear what I’m after is A) Use compose as the primary UI pattern (without resorting to activities/fragments if possible) B) Swap out dependencies of composable functions for testing It seems like this isn’t currently possible without resorting to multiple activities or passing a large number of parameters to each composable function.
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    2 years ago
    It's hard to say without specific code to talk about, but usually the solution to "a large number of parameters" is to accept a slot (a composable function) instead of hard-coding the composable content.
    Robert Menke

    Robert Menke

    2 years ago
    I think I got it working actually - was just being dumb (like most of my programming issues 😅 )
    Ray Ryan

    Ray Ryan

    2 years ago
    That’s how you can tell it’s programming.