gahfy / MVVMPosts

Sample application with MVVM architecture
311 stars 121 forks source link

How to make this code better to support many different view models? #6

Open mfgabriel92 opened 6 years ago

mfgabriel92 commented 6 years ago

Hi,

I copied the code you wrote hoping that it would be a good start for me to write good Android applications applying the Android Architecture Components and two of the most used libraries, Dagger and Retrofit, and I am confident your way is a good way because by what I could see from Google's sample codes, they're similar but simpler. I know there isn't a correct way but more efficient ways, and that is why I write this issue hoping you or someone else can help me, and probably other people, with this problem.

While inspecting what I have copied, it came into my mind about a way to refactor certain parts of the code to adapt it to several different view models. Let's start with the ViewModelInjector.kt class. The inject method expects a PostListViewModel as an argument, and then, this same method is initiated in BaseViewModel.kt, a class that will probably be extended by many other view model classes.

I wanted to try to refactor it and make it more generic and accept a T type as a parameter, but none of what I did help. I no longer have my attempts either. Because the way it is now, the way to support many different view model classes is if I write something like this in ViewModelInjector.kt:

fun injectFoo(fooViewModel: FooViewModel)
fun injectBar(barViewModel: BarViewModel)
...

and then, in the BaseViewModel.kt, do it like this:

init {
    injectFoo()
    injectBar()
}

private fun inject() {
    when (this) {
        is FooViewModel -> injector.injectFoo(this)
        is BarViewModel -> injector.injectBar(this)
    }
}

I'm sure there is a way to fix this and write it in a way that is better, is there not?

I hope someone can help me with this! Thank you.

craicoverflow commented 6 years ago

Hi @mfgabriel92.

It is possible to do this already, inject in ViewModelInjector.kt can be defined multiple times.

ViewModeInjector.kt:

fun inject(fooViewModel: FooViewModel)
fun inject(barViewModel: BarViewModel)

BaseViewModel.kt:

init {
    injectFoo()
    injectBar()
}

private fun inject() {
    when (this) {
        is FooViewModel -> injector.injectthis)
        is BarViewModel -> injector.inject(this)
    }
}

I have created a pull request for @gahfy to review. You can see the updated code in my fork here.