4

I am wondering which one of below two approaches better suit my android application and the reasons for it.

First is using viewmodelfactory pattern and second is viewModelStoreProvider. Can anyone shed some light on these approaches?

First Approach:

@Singleton
class BaseViewModelFactory<T>(val creator: () -> T) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return creator() as T
    }

2.ViewModelStoreOwner code :
class ViewModelStoreProvider
    constructor(viewModelProvider: ViewModelStoreOwner) {

    var viewModelStore: ViewModelStoreOwner = viewModelProvider

    inline fun <reified T : ViewModel> getViewModel(noinline creator: (() -> T)? = null): T {
        return if (creator == null)
            ViewModelProvider(viewModelStore).get(T::class.java)
        else
            ViewModelProvider(viewModelStore, BaseViewModelFactory(creator)).get(T::class.java)
    }
}

And creating instance of view model using below code anywhere in app (Application, activity, fragment)

viewModelStoreProvider.getViewModel { ConfigViewModel(firebaseRemoteConfigRepository)}

Second Approach:

BaseViewModel class :

open class BaseViewModel<N>(
    val dataManager: DataManager,
    val schedulerProvider: SchedulerProvider
) : ViewModel() {
    open var navigator: N? = null
    val compositeDisposable: CompositeDisposable

    init {
        this.compositeDisposable = CompositeDisposable()
    }

    override fun onCleared() {
        compositeDisposable.dispose()
        super.onCleared()
    }
}

class LoginViewModel(dataManager: DataManager, schedulerProvider: SchedulerProvider) :
    BaseViewModel<LoginNavigator>(dataManager, schedulerProvider) {

    override var navigator: LoginNavigator?
        get() = super.navigator
        set(navigator) {
            super.navigator = navigator
        }

    public override fun onCleared() {
        super.onCleared()
    }
}

@Module
class LoginActivityModule {
    @Provides
    internal fun provideLoginViewModel(
        dataManager: DataManager,
        schedulerProvider: SchedulerProvider
    ): LoginViewModel {
        return LoginViewModel(dataManager, schedulerProvider)
    }
}

And we are injecting view model in Activity using

@Inject
override lateinit var viewModel: LoginViewModel
    internal set

Please let me know if anything is unclear and I will do my best to answer it.

avltree
  • 51
  • 4

1 Answers1

4

ViewModelFactory is the right way to create ViewModels with constructor parameters. It will take care of everything related to ViewModel according to its parent Activity/Fragment Lifecycle.

For example, it will keep the same instance during configuration changes, it will call onCleared automatically when activity is destroyed.

With injection approach, you will be responsible for everything related to the lifecycle of ViewModel, like when to create a new instance, how/when onCleared will be called.

Atiq
  • 14,435
  • 6
  • 54
  • 69