Open stanbar opened 6 years ago
DI was out of scope of this, although that does not mean we can discuss about different approaches we can use. Also the fact we are using Dagger is an implementation details. :)
Hi @stasbar , Just curious on your experience in replacing Dagger2. Was it smooth ? or You did a lot of refactoring / changes when shifting the library used?
@android10 You are right, it's implementation detail. But, I was curious if you chose Dagger2 purposely in this project, if it's the clean way of DI.
@crjacinro It was very smooth. I didn't add any new class, interfaces or anything like that. Here is great article about migration from Dagger to KOIN.
Basically removed whole di package and created one file with modules, which is much simpler since you have everything in one place. (Main reason I don't like Dagger, is it classes complexity and high entry point). Additionally I removed all @Inject
annotations, and changed way of injection from
@Inject lateinit var movieDetailsAnimator: MovieDetailsAnimator
private lateinit var movieDetailsViewModel: MovieDetailsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
...
appComponent.inject(this)
movieDetailsViewModel = viewModel(viewModelFactory)
...
}
to
private val movieDetailsAnimator: MovieDetailsAnimator by inject()
private val movieDetailsViewModel: MovieDetailsViewModel by viewModel()
vals always on 👍
I'm quite experienced in KOIN and it's brother project Kodein, so it took me only about 20min.
Okay, but by viewModel()
creates the ViewModel with new instance factory, no? That's typically not what you want and want to use your own ViewModelProvider.Factory
@Zhuinden from the documentation
The by viewModel() function lazily calls the ViewModel class instance and bind it to internal ViewModels factory.
And here is also implementation
fun <T : ViewModel> LifecycleOwner.getViewModelByClass(
fromActivity: Boolean = false,
clazz: KClass<T>,
key: String? = null,
name: String? = null,
parameters: Parameters = emptyParameters()
): T {
KoinFactory.apply {
this.parameters = parameters
this.name = name
}
val viewModelProvider = when {
this is FragmentActivity -> {
Koin.logger.log("[ViewModel] get for FragmentActivity @ $this")
ViewModelProvider(ViewModelStores.of(this), KoinFactory)
}
this is Fragment -> {
if (fromActivity) {
Koin.logger.log("[ViewModel] get for FragmentActivity @ ${this.activity}")
ViewModelProvider(ViewModelStores.of(this.activity), KoinFactory)
} else {
Koin.logger.log("[ViewModel] get for Fragment @ $this")
ViewModelProvider(ViewModelStores.of(this), KoinFactory)
}
}
else -> error("Can't get ViewModel on $this - Is not a FragmentActivity nor a Fragment")
}
return if (key != null) viewModelProvider.get(
key,
clazz.java
) else viewModelProvider.get(clazz.java)
}
where KoinFactory is singleton factory
object KoinFactory : ViewModelProvider.Factory
Hello. Here is a fork where I did migration from Dagger2 to Koin. Take a look how much boilerplate code I was able to get rid of. Don't you think that it's much simpler, easier, faster and cleaner way ?