Last active
April 1, 2019 05:18
-
-
Save alashow/67cc52c606ddc7637e75185673b7f9a6 to your computer and use it in GitHub Desktop.
ViewModel dynamic parameters hack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class AppViewModelFactory @Inject constructor( | |
private val creators: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>> | |
) : ViewModelProvider.Factory { | |
var onViewModelCreate: ((viewModel: ViewModel) -> Unit)? = null | |
override fun <T : ViewModel> create(modelClass: Class<T>): T { | |
var creator: Provider<out ViewModel>? = creators[modelClass] | |
if (creator == null) { | |
for ((key, value) in creators) { | |
if (modelClass.isAssignableFrom(key)) { | |
creator = value | |
break | |
} | |
} | |
} | |
if (creator == null) { | |
throw IllegalArgumentException("unknown model class " + modelClass) | |
} | |
try { | |
@Suppress("UNCHECKED_CAST") | |
val vm = creator.get() as T | |
onViewModelCreate?.invoke(vm) | |
return vm | |
} catch (e: Exception) { | |
throw RuntimeException(e) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class BaseVmActivity<VM : ViewModel> : AppCompatActivity() { | |
@Inject | |
lateinit var viewModelFactory: AppViewModelFactory | |
protected lateinit var vm: VM | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
viewModelFactory.onViewModelCreate = { viewModel -> | |
if (viewModel.javaClass == getVmClass()) { | |
@Suppress("UNCHECKED_CAST") | |
initVm(viewModel as VM) | |
} | |
} | |
vm = getVm(getVmClass()) | |
} | |
/** | |
* Called after [VM]s first time creation. | |
* Can be used for setting initial states of view model. | |
*/ | |
protected open fun initVm(viewModel: VM) {} | |
/** | |
* @return vm class | |
*/ | |
protected abstract fun getVmClass(): Class<VM> | |
protected open fun <S : ViewModel> getVm(clazz: Class<S>): S { | |
return ViewModelProviders.of(this, viewModelFactory).get(clazz) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FeatureActivity : BaseVmActivity<FeatureViewModel>() { | |
override fun initVm(viewModel: FeatureViewModel) { | |
viewModel.init("some-data") | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Module( | |
includes = [ | |
FeatureBinders::class | |
] | |
) | |
class FeatureModule | |
@Module | |
interface FeatureBinders { | |
@ContributesAndroidInjector | |
fun FeatureActivity(): FeatureActivity | |
@Binds | |
@IntoMap | |
@ViewModelKey(FeatureViewModel::class) | |
fun featureViewModel(vm: FeatureViewModel): ViewModel | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FeatureViewModel @Inject constructor(val featureRepository: FeatureRepository) : ViewModel() { | |
fun init(data: String) { | |
// use data somehow | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Module | |
abstract class ViewModelBuilder { | |
@Binds | |
internal abstract fun bindViewModelFactory(factory: AppViewModelFactory): ViewModelProvider.Factory | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) | |
@Retention(AnnotationRetention.RUNTIME) | |
@MapKey | |
annotation class ViewModelKey(val value: KClass<out ViewModel>) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment