ViewModel上的Dagger2 Injection编译错误

时间:2017-10-19 20:57:36

标签: android kotlin dagger-2 android-architecture-components

我在我的应用程序中使用Dagger2最新的Android注入模型(带AndroidInjection类)。到目前为止,一切都运行良好,包括ViewModelFactory注入,但我的ViewModel上只有无参数构造函数。 在实现新功能时,我创建了一个扩展AndroidViewModel的ViewModel(我需要该视图模型中的上下文)。 AndroidViewModel需要Application作为构造函数参数,因此我将其作为注入参数添加到我的ViewModel的构造函数中。 从那时起,Dagger2无法编译并出现以下错误:

  

AppComponent.java:6:错误:[dagger.android.AndroidInjector.inject(T)]   没有@Inject就无法提供android.app.Application   构造函数或来自@ Provide-annotated方法。

我理解这意味着我的Application对象在图表中不可用,但我将其添加到我的App类中,因此我真的不知道如何纠正它。

以下是我的流程中涉及的类。我将标记为我的上一个功能所做的任何更改:

class MobileApp : DaggerApplication() {

    override fun applicationInjector() = DaggerAppComponent.builder()
            .application(this)
            .build()

    override fun onCreate() {
        super.onCreate()
        AppInjectorKt.injectApp(this)
    }
}

AppComponent.kt:

@Singleton
@Component(modules = arrayOf(
        AndroidSupportInjectionModule::class,
        AppModule::class,
        ActivityBuilder::class))
interface AppComponent : AndroidInjector<MobileApp> {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: MobileApp): Builder
        fun build(): AppComponent
    }

    override fun inject(app: MobileApp)
}

AppModule.kt:

@Module(includes = arrayOf(ViewModelModule::class))
class AppModule

ActivityBuilder.kt:

@Module
internal abstract class ActivityBuilder {

    @ContributesAndroidInjector(modules = arrayOf(ResultModule::class))
    internal abstract fun contributeResultActivity(): ResultActivity

//This block is new
    @ContributesAndroidInjector(modules = arrayOf(AltimeterActivityModule::class))
    internal abstract fun contributeAltimeterActivity(): AltimeterActivity

}

ViewModelModule.kt:

@Module
internal abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(ResultViewModel::class)
    abstract fun bindResultViewModel(resultViewModel: ResultViewModel): ViewModel

//This block is new
    @Binds
    @IntoMap
    @ViewModelKey(AltimeterActivityViewModel::class)
    abstract fun bindAltimeterActivityViewModel(altimeterActivityViewModel: AltimeterActivityViewModel): ViewModel

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

}

JumpTrackerViewModelFactory.kt:

@Singleton
class JumpTrackerViewModelFactory @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)
        }
    }
}

ResultActivity.kt:

class ResultActivity : AppCompatActivity(), Injectable {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory


private lateinit var viewModel: ResultViewModel

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

    viewModel = ViewModelProviders.of(this, viewModelFactory)[ResultViewModel::class.java]
[...]

ResultViewModel.kt:

class ResultViewModel @Inject constructor() : ViewModel() {
[...]

AltimeterActivity.kt(这个类是新的):

class AltimeterActivity : AppCompatActivity(), Injectable {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory

    private lateinit var viewModel: AltimeterActivityViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProviders.of(this, viewModelFactory)[AltimeterActivityViewModel::class.java]
[...]

AltimeterActivityViewModel.kt(此类是新的):

class AltimeterActivityViewModel @Inject constructor(app : Application) : AndroidViewModel(app) {

    companion object {
        val TAG = "AltimeterViewModel"
    }

    var pressureAltitudeLiveData = PressureAltitudeLiveData(app)

}

此外,我已经修改了我的代码以尝试App注入,并且它正在工作,所以我知道应用程序有效地正确注入:

AppModule.kt:

@Module(includes = arrayOf(ViewModelModule::class))
class AppModule {

    @Singleton @Provides
    fun provideThing(app : Application) : String {
        return "dqwdwqd"
    }
}

AltimeterActivityViewModel.kt:

class AltimeterActivityViewModel @Inject constructor(/*app : Application*/) : /*Android*/ViewModel(/*app*/) {

    companion object {
        val TAG = "AltimeterViewModel"
    }

//    var pressureAltitudeLiveData = PressureAltitudeLiveData(app)

}

如果有人对发生的事情有任何线索,感谢您分享您的想法!

0 个答案:

没有答案