2017-06-19 14 views
17

tôi đang cố gắng để ràng buộc các lớp con của ViewModel thành một bản đồ bằng KClass loại của họ:Binding Into Bản đồ Với Type KClass

@Module abstract class ViewModelModule { 

    @Binds @IntoMap @ViewModelKey(MyViewModel::class) 
    abstract fun bindsMyViewModel(viewModel: MyViewModel): ViewModel 

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

} 

Nhưng tôi nhận được biên dịch Dagger lỗi:

e: ~/Example/app/build/tmp/kapt3/stubs/debug/com/example/app/injection/AppComponent.java:5: error: [dagger.android.AndroidInjector.inject(T)] java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method. 
e: 

e: public abstract interface AppComponent { 
e:    ^
e:  java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at 
e:   com.example.app.ui.ViewModelFactory.<init>(creators) 
e:  com.example.app.ui.ViewModelFactory is injected at 
e:   com.example.app.injection.ViewModelModule.bindViewModelFactory(p0) 
e:  android.arch.lifecycle.ViewModelProvider.Factory is injected at 
e:   com.example.app.ui.MyFragment.setViewModelFactory(p0) 
e:  com.example.app.ui.MyFragment is injected at 
e:   dagger.android.AndroidInjector.inject(arg0) 

Trên đây ViewModelModule được bao gồm trong số AppModule của tôi, là một mô-đun trong số AppComponent của tôi. Vì vậy, Dagger sẽ có thể cung cấp Map<KClass<out ViewModel>, Provider<ViewModel>> theo yêu cầu của tôi ViewModelFactory, nhưng tôi không thể hiểu tại sao nó bị rơi.


Tôi cũng đã cố gắng chuyển lớp ViewModelKey chú thích trên Java, tham gia một Class như một tham số nhà xây dựng thay vì một KClass. Sau đó sửa đổi ViewModelFactory của tôi để phụ thuộc vào một Map<Class<out ViewModel>, Provider<ViewModel>>, nhưng cùng một lỗi xảy ra.

Trả lời

30

Khi sử dụng KClass trong chú thích, nó thực sự được biên dịch sang số Class của Java. Nhưng vấn đề thực tế là ký tự đại diện trong java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>> mà trình biên dịch Kotlin đang tạo ra.

Giả sử rằng @ViewModelKey được định nghĩa là

@MapKey 
annotation class ViewModelKey(val value: KClass<out ViewModel>) 

Bạn sẽ cần phải xác định vị trí tiêm của bạn như

Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>> 

Sử dụng @JvmSuppressWildcards sẽ ngăn chặn các trình biên dịch từ các kí hiệu tạo ra.

Tôi thực sự không biết, tại sao các ký tự đại diện không được trình biên dịch Dagger hỗ trợ. Bạn có thể gặp sự cố tương tự tại đây: Dagger 2: How to inject Map<Class<? extends Foo>, Provider<? extends Foo>>

+1

Bạn thật tuyệt vời, cảm ơn rất nhiều – Roman

+0

Thật tuyệt vời. Tôi sẽ không bao giờ nhận được điều này, tất cả các dự án Kiến trúc của Google Android đều có trong Java! – Arjun

Các vấn đề liên quan