https://kotlinlang.org logo
#decompose
Title
# decompose
d

Dragos Rachieru

12/08/2023, 11:42 AM
What DI library are you using with Decompose? Right now I am using Kodein and I'm not sure if there is a recommended way to do it.
a

Arkadii Ivanov

12/08/2023, 11:52 AM
Personally I don't use DI frameworks. Though, I created a sample for Dagger - https://github.com/arkivanov/decompose-dagger-sample. For KMP - kotlin-inject should work similarly. Some people are using Koin.
d

Dennis

12/08/2023, 3:03 PM
Iam using Koin and works perfectly
n

Nacho Ruiz Martin

12/08/2023, 4:29 PM
Iam using Koin and works perfectly
@Dennis Out of curiosity, could you make a quick summary on how you instantiate components? I don’t like the way I’m doing it.
d

Dennis

12/08/2023, 5:02 PM
gratitude thank you 1
j

John O'Reilly

12/08/2023, 6:14 PM
Following using Decompose and Koin https://github.com/joreilly/Confetti
gratitude thank you 1
n

Nacho Ruiz Martin

12/08/2023, 6:15 PM
So the idea is to use
by inject
instead of injecting through the constructor, right?
s

s3rius

12/08/2023, 7:56 PM
My advice would be to stick to constructor arguments as much as possible. It makes dependencies clearer to the reader, it's easier to write tests for it, it's easier to control dependencies from the outside (by passing it to the object via constructor arguments). So as I do it, • all dependencies are passed into components via the constructor • parents create child components via
Koin.get()
so that parents don't need to know the dependencies of their children. I'm sailing fairly well with this. Simplified it's this:
Copy code
// All Components are also KoinComponents
interface AppComponentContext : ComponentContext, KoinComponent

// Typesafe creator for new components
inline fun <reified Child : ComponentContext> AppComponentContext.getComponent(key: String) =
    get<Child> { parametersOf(childContext(key)) }

class ParentComponent(
    context: ComponentContext
) : AppComponentContext, ComponentContext by context {
    // ...
    
    // same works for ChildStack, etc
    val child = getComponent<ChildComponent>(key = "child") 
}

class ChildComponent(
    context: ComponentContext,
    otherDependency: WidgetFactory // injected by Koin
) : AppComponentContext, ComponentContext by context {
    // ...
}
This simple example lacks a bunch of functionality. For example, it's not possible for the Parent to pass any dependencies explicitly which you probably want to do some time to time; but that can be added with some tricks.
I would avoid a DI framework entirely if it didn't make dependency management that much easier. No idea how @Arkadii Ivanov deals with more complex scenarios where parent and child components need a variety of different dependencies (use cases, services, etc). I couldn't figure it out, so I had use Koin to help 😛
a

Arkadii Ivanov

12/08/2023, 8:01 PM
In one of my projects I use the same approach as in https://github.com/arkivanov/decompose-dagger-sample, but without a DI framework. So I just writer the code manually that would otherwise generated by Dagger.
So I don't need to write Dagger modules, but I do need a bit of manual wiring (read "calling constructors") on the app side.
Assisted Inject does the trick.
This also lets me have scoped dependencies since I can create a
subDI
for a child component Using it this way, I can add a new dependency for a component and all of its childs, like a composition local
👍 1
5 Views