如何通过 Android/Kotlin App 上的 Koin 注入在 BaseActivity 中 initialize/inject 通用 ViewModel
How to initialize/inject generic ViewModel in BaseActivity by Koin injection on Android/Kotlin App
我正在使用 Kotlin 和 Android 架构组件(ViewModel、LiveData)构建一个新的 Android 应用程序的架构,我还使用 Koin 作为我的依赖注入提供程序。
问题是我无法通过 koin 注入在我的 BaseActivity 中以通用方式初始化 ViewModel。当前代码如下所示:
abstract class BaseActivity<ViewModelType : ViewModel> : AppCompatActivity() {
// This does not compile because of the generic type
private val viewModel by lazy {
// Koin implementation to inject ViewModel
getViewModel<ViewModelType>()
}
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Fabric.with(this, Crashlytics())
}
/**
* Method needed for Calligraphy library configuration
*/
@CallSuper
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase))
}
}
我想知道在 Kotlin 中是否有办法做到这一点,因为我很确定我可以在 Java 中轻松做到。
谢谢
您可以为您的 ViewModel 使用委托版本声明,避免直接使用惰性表达式。试试这个:
abstract class BaseActivity<T : ViewModel> : AppCompatActivity() {
val model by viewModel<T>()
}
这会让你偷懒的
getViewModel<T>()
关注快速参考:https://insert-koin.io/docs/1.0/getting-started/android-viewmodel/
希望对您有所帮助。
解决方案由 koin 团队在 0.9.0-alpha-11
版本中提供,最终代码如下所示:
open class BaseActivity<out ViewModelType : BaseViewModel>(clazz: KClass<ViewModelType>) :
AppCompatActivity() {
val viewModel: ViewModelType by viewModel(clazz)
fun snackbar(message: String?) {
message?.let { longSnackbar(find(android.R.id.content), it) }
}
fun toast(message: String?) {
message?.let { longToast(message) }
}
}
这是不将 Class and Generic
传递给基础实现的示例
在你的基地fragment/activity:
abstract class BaseFragment<T : BaseViewModel> : Fragment() {
...
@Suppress("UNCHECKED_CAST")
private val clazz: KClass<T> = ((this.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>).kotlin
protected val viewModel: T by viewModel(clazz = clazz)
...
}
它看起来很丑,但它确实有效。
我正在使用 Kotlin 和 Android 架构组件(ViewModel、LiveData)构建一个新的 Android 应用程序的架构,我还使用 Koin 作为我的依赖注入提供程序。
问题是我无法通过 koin 注入在我的 BaseActivity 中以通用方式初始化 ViewModel。当前代码如下所示:
abstract class BaseActivity<ViewModelType : ViewModel> : AppCompatActivity() {
// This does not compile because of the generic type
private val viewModel by lazy {
// Koin implementation to inject ViewModel
getViewModel<ViewModelType>()
}
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Fabric.with(this, Crashlytics())
}
/**
* Method needed for Calligraphy library configuration
*/
@CallSuper
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase))
}
}
我想知道在 Kotlin 中是否有办法做到这一点,因为我很确定我可以在 Java 中轻松做到。 谢谢
您可以为您的 ViewModel 使用委托版本声明,避免直接使用惰性表达式。试试这个:
abstract class BaseActivity<T : ViewModel> : AppCompatActivity() {
val model by viewModel<T>()
}
这会让你偷懒的
getViewModel<T>()
关注快速参考:https://insert-koin.io/docs/1.0/getting-started/android-viewmodel/
希望对您有所帮助。
解决方案由 koin 团队在 0.9.0-alpha-11
版本中提供,最终代码如下所示:
open class BaseActivity<out ViewModelType : BaseViewModel>(clazz: KClass<ViewModelType>) :
AppCompatActivity() {
val viewModel: ViewModelType by viewModel(clazz)
fun snackbar(message: String?) {
message?.let { longSnackbar(find(android.R.id.content), it) }
}
fun toast(message: String?) {
message?.let { longToast(message) }
}
}
这是不将 Class and Generic
传递给基础实现的示例
在你的基地fragment/activity:
abstract class BaseFragment<T : BaseViewModel> : Fragment() {
...
@Suppress("UNCHECKED_CAST")
private val clazz: KClass<T> = ((this.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>).kotlin
protected val viewModel: T by viewModel(clazz = clazz)
...
}
它看起来很丑,但它确实有效。