Koin: Can we inject ViewModel Interfaces na

Created on 12 Nov 2018  路  6Comments  路  Source: InsertKoinIO/koin

Is your feature request related to a problem? Please describe.
I don't want to inject the ViewModel implementations in my Activity/Fragment

Describe the solution you'd like
Inject interfaces for my ViewModel

Describe alternatives you've considered
So far my solution look like this

I will have an interface for my viewModel:

    interface ViewModel {
        val events: LiveData<ViewModelEvent>

        fun getLastWeather()
    }

I will have my ViewModel inherit the interface and livecycle.ViewModel:

class SplashViewModel : ViewModel(), SplashContract.ViewModel {

    override val events = SingleLiveEvent<ViewModelEvent>()

    override fun getLastWeather() {
    }
}

I will register my ViewModel like usual:

val weatherAppModule = module {
    viewModel { SplashViewModel(get(), get()) }
}

And use it in the Activity via this line:

    private val splashViewModel: SplashContract.ViewModel by viewModelByClass(SplashViewModel::class)

Target Koin project
not sure

android check

Most helpful comment

You can't use an interface for viewModel since unfortunately the base ViewModel is an abstract class and the ViewModelProvider.Factory methods require the provided viewmodel inherits from ViewModel.

But you can achieve the separation of interface and implementation by making the interface an abstract class instead.

// "interface"
abstract class FooViewModel {
    abstract val events: LiveData<ViewModelEvent>

    abstract fun getLastWeather()
}

// implementation
class FooViewModelImpl : FooViewModel() {
    override val events = SingleLiveEvent<ViewModelEvent>()

    override fun getLastWeather() {
    }
}

and then

viewModel<FooViewModel> { FooViewModelImpl() }

That is probably the closest you will get without some hacky workarounds

All 6 comments

Any updates on this? Thanks!

viewModel { FooBarImpl() as FooBar }

@alexandru-calinoiu It looks like you ar enot using the Android ViewModel but instead define your own interface. In that case you don't need the viewModel {} definitions at all - a simple factory {} suffices. You inject them with by inject().

You can't use an interface for viewModel since unfortunately the base ViewModel is an abstract class and the ViewModelProvider.Factory methods require the provided viewmodel inherits from ViewModel.

But you can achieve the separation of interface and implementation by making the interface an abstract class instead.

// "interface"
abstract class FooViewModel {
    abstract val events: LiveData<ViewModelEvent>

    abstract fun getLastWeather()
}

// implementation
class FooViewModelImpl : FooViewModel() {
    override val events = SingleLiveEvent<ViewModelEvent>()

    override fun getLastWeather() {
    }
}

and then

viewModel<FooViewModel> { FooViewModelImpl() }

That is probably the closest you will get without some hacky workarounds

this last message is the best way to do that IMO

I found a way to do this, by overriding Koin extension functions. Please check my stackoverflow answer. Although I think abstract class is the way to go.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

CristianMG picture CristianMG  路  3Comments

leodeleon22 picture leodeleon22  路  4Comments

AHarazim picture AHarazim  路  3Comments

TedHoryczun picture TedHoryczun  路  4Comments

haroldadmin picture haroldadmin  路  3Comments