Dagger无法使用KClass注入ViewModel

问题描述 投票:0回答:1

我正在将我的项目java移动到kotlin,但是对KClassClass有些困惑

这是我的BaseActivity

abstract class BaseActivity<DB : ViewDataBinding, VM : BaseViewModel> : DaggerAppCompatActivity() {

    private lateinit var mCustomDialog: CustomDialog
    private lateinit var mViewDataBinding: DB
    private lateinit var mViewModel : VM

    @Inject
    lateinit var viewModelFactory: ViewModelFactory

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Set Custom Dialog
        mCustomDialog = CustomDialog(this, R.style.LoadingDialogStyle)
        // Set ViewModel
        mViewModel = ViewModelProviders.of(this, viewModelFactory).get(getViewModelClass().java)
        // Set DataBinding
        mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId())
        mViewDataBinding.lifecycleOwner = this
        mViewDataBinding.setVariable(getBindingVariable(), mViewModel)
        mViewDataBinding.executePendingBindings()
        // Initialize UI
        prepareView(savedInstanceState)
    }


    @LayoutRes
    abstract fun getLayoutId(): Int


    protected abstract fun getViewModelClass(): KClass<VM>


    abstract fun getBindingVariable(): Int


    fun getViewModel(): VM {
        return mViewModel
    }


    fun getViewDataBinding() : DB {
        return mViewDataBinding
    }

我在下面的函数中使用protected abstract fun getViewModelClass(): KClass<VM>函数初始化ViewModel

ViewModelProviders.of(this, viewModelFactory).get(getViewModelClass().java)

我通过这种方式在活动中使用ViewModel

class SplashActivity : BaseActivity<ActivitySplashBinding, SplashViewModel>() {

    override fun getViewModelClass(): KClass<SplashViewModel> {
        return SplashViewModel::class
    }

    override fun getLayoutId(): Int {
        return R.layout.activity_splash
    }

    override fun getBindingVariable(): Int {
        return BR.vm
    }

    override fun prepareView(savedInstanceState: Bundle?) {
        getViewModel().testLog()
    }

}

但是当我运行项目时,我收到了这个错误

error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.example.example.MyApp> {
                ^
      java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
          com.example.example.utils.ViewModelFactory(viewModels)
      com.example.example.utils.ViewModelFactory is injected at
          com.example.example.base.BaseActivity.viewModelFactory
      com.example.example.ui.splash.SplashActivity is injected at
          dagger.android.AndroidInjector.inject(T) [com.example.example.di.AppComponent ? com.example.example.di.ActivityBindingsModule_SplashActivityInjector$app_debug.SplashActivitySubcomponent]

所以我做了一些研究,发现它是关于我的KClass中的ViewModelKey

这是ViewModelKey

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)

如果我不将我的代码更改为Kotlin并使用这样的旧Java类,则它可以正常工作

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
    Class<? extends ViewModel> value();
}

这是我的ViewModelFactory课程

@Suppress("UNCHECKED_CAST")
class ViewModelFactory @Inject
constructor(private val viewModels: MutableMap<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        val creator = viewModels[modelClass]
            ?: viewModels.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
            ?: throw IllegalArgumentException("unknown model class $modelClass")
        return try {
            creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

我的SplashActivityModule

@Module
abstract class SplashActivityModule {

    @Binds
    @IntoMap
    @ViewModelKey(SplashViewModel::class)
    internal abstract fun provideSplashViewModel(splashViewModel: SplashViewModel) : ViewModel

}

那么我如何才能与Kotlin正确使用ViewModelKey以及这个错误的主要原因,任何帮助将不胜感激

mvvm kotlin dependency-injection viewmodel dagger-2
1个回答
0
投票

你的ViewModelKey就像

@MustBeDocumented
@kotlin.annotation.Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
© www.soinside.com 2019 - 2024. All rights reserved.