使用Dagger注入Kotlin时出错

时间:2018-03-14 09:23:36

标签: android kotlin dagger-2

我试图在ViewModel中注入ModelViewFactory对象,我收到以下错误。一直在研究这个好几天似乎无法弄明白。

public abstract interface MinutemanComponent {
            ^
  com.xyz.minuteman.view.meeting.detail.MeetingItemDetailsViewModel is injected at
      com.xyz.minuteman.injection.ViewModelModule.bindMeetingItemDetailsViewModel(meetingItemDetailsViewModel)
  java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
      com.xyz.minuteman.injection.ViewModelFactory.<init>(creators)
  com.xyz.minuteman.injection.ViewModelFactory is injected at
      com.xyz.minuteman.injection.ViewModelModule.bindViewModelFactory(viewModelFactory)
  android.arch.lifecycle.ViewModelProvider.Factory is injected at
      com.xyz.minuteman.view.meeting.list.MeetingListFragment.viewModelFactory
  com.xyz.minuteman.view.meeting.list.MeetingListFragment is injected at
      dagger.android.AndroidInjector.inject(arg0)

这是我的ViewModelFactory

class ViewModelFactory @Inject constructor(
    private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>)
: ViewModelProvider.Factory {

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
    var creator: Provider<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 {
        return creator.get() as T
    } catch (e: Exception) {
        throw RuntimeException(e)
    }
}

}

这是片段,我试图注入viewModelFactory

class MeetingListFragment : Fragment(), Injectable {

@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory

private lateinit var meetingsListViewModel: MeetingsListViewModel
private lateinit var adapter: MeetingAdapter

private val itemClickListener = View.OnClickListener { v: View ->
    val meeting = v.tag as Meeting
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
    val v = inflater.inflate(R.layout.fragment_list_previous_meetings_layout, container, false)
    setupRecyclerView(v)

    meetingsListViewModel = ViewModelProviders.of(this, viewModelFactory).get(MeetingsListViewModel::class.java)
    meetingsListViewModel!!.getAllMeetings().observe(this, Observer { r ->
        if (r != null) {
            adapter.setItems(r)
        }
    })
    return v;
}

private fun setupRecyclerView(v: View) {
    val recyclerView = v.findViewById<RecyclerView>(R.id.recyclerview_meeting_list)
    val layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
    recyclerView?.layoutManager = layoutManager

    adapter = MeetingAdapter(ArrayList(), recyclerView.context, itemClickListener)
    recyclerView?.adapter = adapter
    val dividerItemDecoration = DividerItemDecoration(recyclerView?.context,
            layoutManager.orientation)
    recyclerView?.addItemDecoration(dividerItemDecoration)
}

}

这是ViewModel模块,其中我有ViewModels的Provider方法

   @Module
abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(MeetingsListViewModel::class)
    abstract fun bindMeetingsListViewModel(meetingsListViewModel: MeetingsListViewModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(MeetingItemDetailsViewModel::class)
    abstract fun bindMeetingItemDetailsViewModel(meetingItemDetailsViewModel: MeetingItemDetailsViewModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(AddMeetingViewModel::class)
    abstract fun bindAddMeetingViewModel(addMeetingViewModel: AddMeetingViewModel): ViewModel

    @Binds
    abstract fun bindViewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory

}

这里也是FragmentBuilderModule

    @Module
abstract class FragmentBuilderModule {
    @ContributesAndroidInjector
    abstract fun contributeMeetingListFragment(): MeetingListFragment
}

这是App Component

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class,
ActivityBuilderModule::class,
MinutemanModule::class])
interface MinutemanComponent {

    fun inject(minutemanApplication: MinutemanApplication)

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: MinutemanApplication): Builder

        fun build(): MinutemanComponent
    }

}

2 个答案:

答案 0 :(得分:2)

并非ViewModelModule中提供的所有ViewModel在构造函数上都有@Inject,我将其添加到所有这些中,它解决了我的问题。

答案 1 :(得分:0)

您似乎永远不会使用ViewModelModule。将您的MinutemanComponent更改为以下内容:

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class,
ActivityBuilderModule::class, MinutemanModule::class, ViewModelModule::class])
interface MinutemanComponent {

    fun inject(minutemanApplication: MinutemanApplication)

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: MinutemanApplication): Builder

        fun build(): MinutemanComponent
    }

}