Skip to content

Commit

Permalink
467 add viewmodel saved state support
Browse files Browse the repository at this point in the history
  • Loading branch information
kedzie committed Jun 14, 2019
1 parent fcd6a63 commit ded233d
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 15 deletions.
1 change: 1 addition & 0 deletions koin-projects/examples/androidx-samples/build.gradle
Expand Up @@ -31,6 +31,7 @@ dependencies {

implementation "androidx.appcompat:appcompat:$androidx_lib_version"
implementation "androidx.lifecycle:lifecycle-extensions:$android_arch_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha01"
implementation "org.jetbrains.anko:anko-commons:$anko_version"

}
@@ -0,0 +1,7 @@
package org.koin.sample.androidx.components.mvvm

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import org.koin.sample.androidx.components.main.Service

class SavedStateViewModel(val handle: SavedStateHandle, val id: String, val service: Service) : ViewModel()
@@ -1,5 +1,6 @@
package org.koin.sample.androidx.di

import androidx.lifecycle.SavedStateHandle
import org.koin.androidx.experimental.dsl.viewModel
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.qualifier.named
Expand All @@ -15,6 +16,7 @@ import org.koin.sample.androidx.components.main.ServiceImpl
import org.koin.sample.androidx.components.mvp.FactoryPresenter
import org.koin.sample.androidx.components.mvp.ScopedPresenter
import org.koin.sample.androidx.components.mvvm.ExtSimpleViewModel
import org.koin.sample.androidx.components.mvvm.SavedStateViewModel
import org.koin.sample.androidx.components.mvvm.SimpleViewModel
import org.koin.sample.androidx.components.scope.Session
import org.koin.sample.androidx.mvp.MVPActivity
Expand Down Expand Up @@ -43,6 +45,7 @@ val mvvmModule = module {
viewModel(named("vm1")) { (id: String) -> SimpleViewModel(id, get()) }
viewModel(named("vm2")) { (id: String) -> SimpleViewModel(id, get()) }

viewModel { (handle: SavedStateHandle, id: String) -> SavedStateViewModel(handle, id, get()) }

scope(named<MVVMActivity>()) {
scoped { Session() }
Expand Down
Expand Up @@ -8,11 +8,13 @@ import org.koin.android.ext.android.getKoin
import org.koin.androidx.scope.currentScope
import org.koin.androidx.viewmodel.ext.android.getViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.androidx.viewmodel.ext.android.viewModelWithState
import org.koin.core.parameter.parametersOf
import org.koin.core.qualifier.named
import org.koin.sample.android.R
import org.koin.sample.androidx.components.ID
import org.koin.sample.androidx.components.mvvm.ExtSimpleViewModel
import org.koin.sample.androidx.components.mvvm.SavedStateViewModel
import org.koin.sample.androidx.components.mvvm.SimpleViewModel
import org.koin.sample.androidx.components.scope.Session
import org.koin.sample.androidx.scope.ScopedActivityA
Expand All @@ -28,6 +30,9 @@ class MVVMActivity : AppCompatActivity() {
val scopeVm: ExtSimpleViewModel by currentScope.viewModel(this)
val extScopeVm: ExtSimpleViewModel by currentScope.viewModel(this, named("ext"))

val savedVm: SavedStateViewModel by viewModelWithState(defaultArguments = Bundle()) { parametersOf("vm2") }
val scopedSavedVm: SavedStateViewModel by currentScope.viewModelWithState(this, defaultArguments = Bundle()) { parametersOf("vm2") }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand Down
7 changes: 7 additions & 0 deletions koin-projects/koin-androidx-ext/build.gradle
Expand Up @@ -34,6 +34,13 @@ dependencies {
exclude module: "runtime"
exclude group: "androidx.legacy"
}
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha01") {
exclude module: "lifecycle-livedata"
exclude module: "lifecycle-service"
exclude module: "lifecycle-process"
exclude module: "runtime"
exclude group: "androidx.legacy"
}
}

apply from: '../gradle/publish-android.gradle'
8 changes: 8 additions & 0 deletions koin-projects/koin-androidx-viewmodel/build.gradle
Expand Up @@ -33,6 +33,14 @@ dependencies {
exclude module: "runtime"
exclude group: "androidx.legacy"
}

implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha01") {
exclude module: "lifecycle-livedata"
exclude module: "lifecycle-service"
exclude module: "lifecycle-process"
exclude module: "runtime"
exclude group: "androidx.legacy"
}
}

apply from: '../gradle/publish-android.gradle'
@@ -1,5 +1,6 @@
package org.koin.androidx.viewmodel

import android.os.Bundle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModelStoreOwner
import org.koin.core.parameter.ParametersDefinition
Expand All @@ -8,6 +9,7 @@ import kotlin.reflect.KClass

class ViewModelParameters<T : Any>(
val clazz: KClass<T>,
val defaultArguments: Bundle?,
val owner: LifecycleOwner,
val qualifier: Qualifier? = null,
val from: ViewModelStoreOwnerDefinition? = null,
Expand Down
Expand Up @@ -2,14 +2,14 @@ package org.koin.androidx.viewmodel

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.*
import androidx.savedstate.SavedStateRegistryOwner
import org.koin.core.Koin
import org.koin.core.KoinApplication
import org.koin.core.KoinApplication.Companion.logger
import org.koin.core.logger.Level
import org.koin.core.parameter.emptyParametersHolder
import org.koin.core.parameter.parametersOf
import org.koin.core.scope.Scope
import org.koin.core.time.measureDuration

Expand Down Expand Up @@ -66,4 +66,27 @@ fun <T : ViewModel> Scope.createViewModelProvider(
return get(parameters.clazz, parameters.qualifier, parameters.parameters)
}
})
}

//saved state

fun <T : ViewModel> Koin.getViewModelWithState(parameters: ViewModelParameters<T>): T {
val vmStore: ViewModelStore = parameters.owner.getViewModelStore(parameters)
val viewModelProvider = rootScope.createSavedStateViewModelProvider(vmStore, parameters)
return viewModelProvider.getInstance(parameters)
}

fun <T : ViewModel> Scope.createSavedStateViewModelProvider(
vmStore: ViewModelStore,
parameters: ViewModelParameters<T>
): ViewModelProvider {
return ViewModelProvider(
vmStore,
object : AbstractSavedStateVMFactory(vmStore as SavedStateRegistryOwner, parameters.defaultArguments) {
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
return get(parameters.clazz, parameters.qualifier) {
parametersOf(handle, *(parameters.parameters?.invoke() ?: emptyParametersHolder()).values)
}
}
})
}
Expand Up @@ -12,4 +12,14 @@ fun <T : ViewModel> Scope.getViewModel(parameters: ViewModelParameters<T>): T {
val vmStore: ViewModelStore = parameters.owner.getViewModelStore(parameters)
val viewModelProvider = createViewModelProvider(vmStore, parameters)
return viewModelProvider.getInstance(parameters)
}

/**
* resolve instance with state
* @param parameters
*/
fun <T : ViewModel> Scope.getViewModelWithState(parameters: ViewModelParameters<T>): T {
val vmStore: ViewModelStore = parameters.owner.getViewModelStore(parameters)
val viewModelProvider = createSavedStateViewModelProvider(vmStore, parameters)
return viewModelProvider.getInstance(parameters)
}
Expand Up @@ -92,6 +92,7 @@ fun <T : ViewModel> Fragment.getSharedViewModel(
return getKoin().getViewModel(
ViewModelParameters(
clazz,
null,
this@getSharedViewModel,
qualifier,
from,
Expand Down
Expand Up @@ -16,11 +16,13 @@
package org.koin.androidx.viewmodel.ext.android

import android.content.ComponentCallbacks
import android.os.Bundle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import org.koin.android.ext.android.getKoin
import org.koin.androidx.viewmodel.ViewModelParameters
import org.koin.androidx.viewmodel.getViewModel
import org.koin.androidx.viewmodel.getViewModelWithState
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import kotlin.reflect.KClass
Expand All @@ -44,17 +46,6 @@ fun <T : ViewModel> LifecycleOwner.viewModel(
parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModel(clazz, qualifier, parameters) }

/**
* Lazy getByClass a viewModel instance
*
* @param qualifier - Koin BeanDefinition qualifier (if have several ViewModel beanDefinition of the same type)
* @param parameters - parameters to pass to the BeanDefinition
*/
inline fun <reified T : ViewModel> LifecycleOwner.viewModel(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModel<T>(qualifier, parameters) }

/**
* Get a viewModel instance
*
Expand Down Expand Up @@ -85,9 +76,62 @@ fun <T : ViewModel> LifecycleOwner.getViewModel(
return getKoin().getViewModel(
ViewModelParameters(
clazz,
null,
this@getViewModel,
qualifier,
parameters = parameters
)
)
}

/**
* Lazy getByClass a viewModel instance
*
* @param qualifier - Koin BeanDefinition qualifier (if have several ViewModel beanDefinition of the same type)
* @param parameters - parameters to pass to the BeanDefinition
*/
inline fun <reified T : ViewModel> LifecycleOwner.viewModel(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModel<T>(qualifier, parameters) }


//saved state

fun <T : ViewModel> LifecycleOwner.getViewModelWithState(
clazz: KClass<T>,
defaultArguments: Bundle?,
qualifier: Qualifier? = null,
parameters: ParametersDefinition? = null
): T {
return getKoin().getViewModelWithState(
ViewModelParameters(
clazz,
defaultArguments,
this@getViewModelWithState,
qualifier,
parameters = parameters
)
)
}

inline fun <reified T : ViewModel> LifecycleOwner.getViewModelWithState(
defaultArguments: Bundle?,
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): T {
return getViewModelWithState(T::class, defaultArguments, qualifier, parameters)
}

fun <T : ViewModel> LifecycleOwner.viewModelWithState(
clazz: KClass<T>,
qualifier: Qualifier? = null,
defaultArguments: Bundle? = null,
parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModelWithState(clazz, defaultArguments, qualifier, parameters) }

inline fun <reified T : ViewModel> LifecycleOwner.viewModelWithState(
qualifier: Qualifier? = null,
defaultArguments: Bundle? = null,
noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModelWithState<T>(defaultArguments, qualifier, parameters) }
Expand Up @@ -15,10 +15,12 @@
*/
package org.koin.androidx.viewmodel.ext.android

import android.os.Bundle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import org.koin.androidx.viewmodel.ViewModelParameters
import org.koin.androidx.viewmodel.getViewModel
import org.koin.androidx.viewmodel.getViewModelWithState
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import org.koin.core.scope.Scope
Expand Down Expand Up @@ -86,6 +88,76 @@ fun <T : ViewModel> Scope.getViewModel(
return getViewModel(
ViewModelParameters(
clazz,
null,
owner,
qualifier,
parameters = parameters
)
)
}

//saved state
/**
* Lazy get a viewModel instance
*
* @param qualifier - Koin BeanDefinition qualifier (if have several ViewModel beanDefinition of the same type)
* @param parameters - parameters to pass to the BeanDefinition
* @param clazz
*/
fun <T : ViewModel> Scope.viewModelWithState(
owner: LifecycleOwner,
clazz: KClass<T>,
qualifier: Qualifier? = null,
defaultArguments: Bundle?,
parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModelWithState(owner, clazz, qualifier, defaultArguments, parameters) }

/**
* Lazy getByClass a viewModel instance
*
* @param qualifier - Koin BeanDefinition qualifier (if have several ViewModel beanDefinition of the same type)
* @param parameters - parameters to pass to the BeanDefinition
*/
inline fun <reified T : ViewModel> Scope.viewModelWithState(
owner: LifecycleOwner,
qualifier: Qualifier? = null,
defaultArguments: Bundle?,
noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModelWithState<T>(owner, qualifier, defaultArguments, parameters) }

/**
* Get a viewModel instance
*
* @param qualifier - Koin BeanDefinition qualifier (if have several ViewModel beanDefinition of the same type)
* @param parameters - parameters to pass to the BeanDefinition
*/
inline fun <reified T : ViewModel> Scope.getViewModelWithState(
owner: LifecycleOwner,
qualifier: Qualifier? = null,
defaultArguments: Bundle?,
noinline parameters: ParametersDefinition? = null
): T {
return getViewModelWithState(owner, T::class, qualifier, defaultArguments, parameters)
}

/**
* Lazy getByClass a viewModel instance
*
* @param clazz - Class of the BeanDefinition to retrieve
* @param qualifier - Koin BeanDefinition qualifier (if have several ViewModel beanDefinition of the same type)
* @param parameters - parameters to pass to the BeanDefinition
*/
fun <T : ViewModel> Scope.getViewModelWithState(
owner: LifecycleOwner,
clazz: KClass<T>,
qualifier: Qualifier? = null,
defaultArguments: Bundle?,
parameters: ParametersDefinition? = null
): T {
return getViewModelWithState(
ViewModelParameters(
clazz,
defaultArguments,
owner,
qualifier,
parameters = parameters
Expand Down

0 comments on commit ded233d

Please sign in to comment.