【问题标题】:Dagger2 Map multibinding : What do I provide for this java.util.Map<java.lang.Class<?.....> for viewmodel map multibinding? [duplicate]Dagger2 Map multibinding:我为这个 java.util.Map<java.lang.Class<?.....> 为 viewmodel map multibinding 提供什么? [复制]
【发布时间】:2020-02-02 08:39:58
【问题描述】:

我想通过 dagger 提供视图模型,所以我使用了具有地图多重绑定的 ViewModelProviderFactory。这是 ViewModelProviderFactory.kt 的代码:

@Singleton
class ViewModelProviderFactory @Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>) : ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T = viewModels[modelClass]?.get() as T
}

这是我的 ViewModelFactoryModule.kt :

@Module
abstract class ViewModelFactoryModule {

    @Binds
    abstract fun bindViewModelFactory(providerFactory: ViewModelProviderFactory) : ViewModelProvider.Factory

}

这是我的 ViewModelKey.kt :

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

}

我想将 AuthViewModel 添加到名为 Login 的活动中,这是我的 AuthViewModelModule.kt :

@Module
abstract class AuthViewModelModule {
    @Binds
    @IntoMap
    @ViewModelKey(AuthViewModel::class)
    abstract fun bindAuthViewModel(viewModel : AuthViewModel) : ViewModel
}

这是 Login.kt :

class Login : AppCompatActivity() {
    @Inject
    lateinit var providerFactory : ViewModelProviderFactory

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

        val api = Api.instance

        val repository = UserRepository(api)

        val factory = AuthViewModelFactory(repository)

        val binding: ActivityLoginBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_login)

        val viewModel = ViewModelProvider(this, providerFactory).get(AuthViewModel::class.java)

        binding.viewmodel = viewModel

    }

}

这是我的 AppComponent.kt

@Singleton
@Component(
    modules = [
        AndroidSupportInjectionModule::class,
        ActivityBuildersModule::class,
        AppModule::class,
        ViewModelFactoryModule::class
    ]
)
interface AppComponent : AndroidInjector<BaseApplication> {

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application) : Builder

        fun build() : AppComponent
    }
}

还有我的 ActivityBuildersModule.kt :

@Module
abstract class ActivityBuildersModule {

    @ContributesAndroidInjector(
        modules = [AuthViewModelModule::class]
    )
    abstract fun contributeLogin() : Login
}

这是我的 AppModule.kt :

@Module
class AppModule {
    @Module
    companion object
    {
        @Provides
        @JvmStatic
        fun providesAppNull(application: Application) : Boolean = application == null
        }
    }

}

这是我的 AuthViewModel:

class AuthViewModel @Inject constructor(
) : ViewModel() {
    var name: String? = null
    var email: String? = null
    var password: String? = null
    var password_confirm: String? = null

    var authListener: AuthListener? = null


    fun onSignUpButtonClicked(view: View) {
        authListener?.onStarted()
        val mContext = view.context

        if (name.isNullOrEmpty() || email.isNullOrEmpty() || password.isNullOrEmpty() || password_confirm.isNullOrEmpty()) {
            authListener?.onFailure("Invalid email or password!")
            return
        } else if (!password.equals(password_confirm)) {
            authListener?.onFailure("Passwords do not match!!!")
            return
        } else {
            Log.d("AuthViewModel", "doing something")
        }
    }
}

而不是注入所有这些,我得到了没有提供的错误,这是我现在得到的错误:

java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.kreeti.gogal.viewmodels.ViewModelProviderFactory(viewModels)
com.kreeti.gogal.viewmodels.ViewModelProviderFactory is injected at
com.kreeti.gogal.di.ViewModelFactoryModule.bindViewModelFactory(providerFactory)
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.kreeti.gogal.ui.auth.Login.providerFactory
com.kreeti.gogal.ui.auth.Login is injected at

【问题讨论】:

  • 你能添加你的AppModule吗?
  • this 有帮助吗?
  • 是的,这解决了我的问题,谢谢:)

标签: android kotlin dagger-2 dagger android-viewmodel


【解决方案1】:

您应该注入 viewModel 类的构造函数 例子: @注入 公共 AuthViewModel(){} 它应该可以正常工作。

【讨论】:

  • 我已经编辑了我的答案,它已经有@Inject 注释,但我仍然收到此错误
【解决方案2】:

只需将此代码转换为 kotlin,然后替换原来的代码

导入 java.util.Map;导入 javax.inject.Inject;导入 javax.inject.Provider;导入 javax.inject.Singleton;导入androidx.lifecycle.ViewModel;导入androidx.lifecycle.ViewModelProvider;公共类 ViewModelProviderFactory 实现 ViewModelProvider.Factory { private static final String TAG = "ViewModelProviderFactor"; private final Map, Provider> creators; @Inject public ViewModelProviderFactory(Map, Provider> creators) { this.creators = creators; } @Override public T create(Class modelClass) { Provider creator = creators.get(modelClass); if (creator == null) { // 如果视图模型尚未创建 // 循环遍历允许的键(也就是带有 @ViewModelKey 的允许类) for (Map.Entry, Provider> entry : creators.entrySet()) { // 如果允许,设置提供者 if (modelClass.isAssignableFrom(entry.getKey())) { creator = entry.getValue();休息; } } } // 如果这不是允许的键之一,则抛出异常 if (creator == null) { throw new IllegalArgumentException("unknown model class " + modelClass); } // 返回提供者 try { return (T) creator.get(); } catch (Exception e) { throw new RuntimeException(e); } }}

【讨论】:

  • 此代码未格式化且不可读。在发布答案时,请花一些时间来格式化您的代码。此外,这个问题要求的是 Kotlin,而不是 Java。
猜你喜欢
  • 2011-09-24
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 2019-01-31
相关资源
最近更新 更多