l

    Lauren Yew

    1 year ago
    Are 
    Providers
      and 
    Ambients
     like a Dagger inject where I can get a dependency without passing it as a param anywhere? Is there a best practice on their use? https://developer.android.com/reference/kotlin/androidx/compose/runtime/Ambient
    j

    jw

    1 year ago
    They are not like Dagger, where dependencies are declared in public API. They are like a service locator, where the dependencies are implementation detail. They're similar to
    Context.getSystemService
    .
    l

    Lauren Yew

    1 year ago
    But it seems like I can use them to pass any custom data class
    Sort of like a Dagger singleton inject
    at least based on the
    ActiveUser
    example in the doc
    j

    jw

    1 year ago
    No, in Dagger the dependency would be exposed on the public API and thus validated that it was supplied in order to create the thing. In Compose nothing validates that ambients are provided and you can and will get runtime failures when they are missing. It's a service locator, not a dependency injector.
    l

    Lauren Yew

    1 year ago
    ok thanks
    rsktash

    rsktash

    1 year ago
    Hello @jw what is the best practice for injecting in compose project?
    Adam Powell

    Adam Powell

    1 year ago
    Well, you get the default value for that ambient if nothing above provided it. It's kind of bad form to declare the default value as
    { error("missing foo") }
    but you can if you really want to
    Otherwise, yes exactly 🙂
    j

    jw

    1 year ago
    Calling
    Context.getSystemService(VIBRATOR)
    will crash on devices without a vibrator motor if you're not careful! But the last time I remember seeing that was like 2011... Seems like your only choice is an explicit argument or the ambient system, although the Compose i've done is not Compose UI and I have never used ambients so my advice is likely not that useful.
    rsktash

    rsktash

    1 year ago
    When we choose explicit argument there may be a lot of function params as hierarchy tree is very deep in bigger projects
    In my opinion there will be parent composable components where lifecycle of dependencies are managed, injected and destroyed and also child composable components with arguments where rendering is done
    k

    Kirill Grouchnikov

    1 year ago
    Context.getSystemService
    is really a global object that can't be "redefined". Ambients in Compose can be redefined (or provided) at any level in the hierarchy, and that applies to the entire subtree unless some subchild redefines it again.
    So it's a bit more powerful. But don't abuse it for passing app data around your composables.
    l

    Lauren Yew

    1 year ago
    What would you use it for? Examples would be appreciated. The example in the doc looks like just passing app data.
    k

    Kirill Grouchnikov

    1 year ago
    At the global level, there are ambients for density, ltr/rtl and other global values
    But you shouldn't use ambients to hold on to application data. That should be passed explicitly to your composables
    Adam Powell

    Adam Powell

    1 year ago
    theming information and
    Context.getSystemService
    -type things are what we tend to use them for in the stock compose libraries
    k

    Kirill Grouchnikov

    1 year ago
    On the other hand, a concept of "accent color" in Material would be too invasive, if you will, to pass everywhere you want to use it. So as part of theming, it is set and queried in an ambient.
    Adam Powell

    Adam Powell

    1 year ago
    Ambients behave very similarly to react's Context; the advice here is nearly all applicable: https://reactjs.org/docs/context.html
    in particular, the advice to use higher-order components (or in compose's case, composable functions) often removes the pressure to use something like ambients
    when more traditional DI comes into play, injecting the objects that you pass to composable functions as normal parameters gets you pretty far
    multiple receivers for extension functions is also a direction to watch in this same space if you're looking for DI-like compile-time validation: https://youtrack.jetbrains.com/issue/KT-10468
    rsktash

    rsktash

    1 year ago
    Hi @Adam Powell, So anyway in the middle of component hierarchy tree you will have to pass new dependencies as you need. For this situation we will have to create instances and pass it to child components and destroy on dispose. Am I wrong?
    Adam Powell

    Adam Powell

    1 year ago
    managing object lifetimes is yet another layer to the question; generally it's a good idea to keep the same code that creates an object responsible for ensuring it's disposed properly if needed
    DisposableEffect
    is one way to initialize/tear down an object that needs it; we also still need to add some sort of
    rememberDisposable
    that does it in one go with creating something in a
    remember
    expression. There are some edge cases where
    DisposableEffect
    won't clean up an object created in a
    remember
    expression if the composition pass where the object was created fails
    v

    Vinay Gaba

    1 year ago
    @Sean McQuillan [G] Tries to answer this exact question (role of dependency injection in a Compose world) here - https://www.droidcon.com/media-detail?video=481211040 Go to 21:28 in the video.
    j

    jw

    1 year ago
    This thread is long, but we absolutely use Context.getSystemService like ambients today. Layers of our app wrap the context and shadow available types. We use it to propagate theme information, for example.
    We've been doing this for many many years now for things which are always available in the view tree such as location information, the navigator, and theme info. As far as I can tell, ambients are exactly the same with sole difference being they're effectively a stream which triggers recomposition on value change whereas system service require polling for changes.
    Colton Idle

    Colton Idle

    1 year ago
    @Lauren Yew good question and nice to hear the answers above. Thanks for asking it!