android - 使用 Dagger 2 注入(inject) Androidx Activity

标签 android dependency-injection dagger-2 dagger

我是 Android 中使用 Dagger 进行依赖注入(inject)的新手

我有这个错误 Unable to start activity ComponentInfo{MainActivity}: kotlin.UninitializedPropertyAccessException: lateinit property dispatchingAndroidInjector has not been initialized

我不知道我的代码中的确切错误是什么,我应该更改一些东西吗?尽管在我从事的另一个项目中,它们具有相同的代码,除了 AndroidInjection.inject(this) 并且代码运行良好

非常感谢您的帮助

这是我的文件:

应用组件

@Singleton
@Component(
modules = [AndroidSupportInjectionModule::class,
    AppModule::class, NetworkModule::class,
    ActivityBuilder::class]
)
interface AppComponent : AndroidInjector<Application> {

@Component.Builder
interface Builder {
    @BindsInstance
    fun application(application: Application): Builder

    fun build(): AppComponent
}

应用模块

@Module(includes = [ViewModelModule::class])

类 AppModule {

@Provides
fun provideContext(application: MyApplication): Context {
    return application.applicationContext
}

@Provides
fun provideHandler(): Handler {
    return Handler()
}

@Provides
@Singleton
fun provideSharedPreferences(context: Context): SharedPreferences {
    return context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
}

@Provides
@Singleton
fun provideSharedPreferenceUtils(context: Context): SharedPreferenceUtils {
    return SharedPreferenceUtils(provideSharedPreferences(context))
}

Activity 构建器

@Module
abstract class ActivityBuilder {

@ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity

网络模块

@Module(includes = [AppModule::class])
// Safe here as we are dealing with a Dagger 2 module
@Suppress("unused")
class NetworkModule {

@Provides
@Singleton
fun provideCache(context: Context): Cache {
    return Cache(context.cacheDir, CACHE_SIZE)
}

@Provides
@Singleton
fun provideOkHttpClient(cache: Cache, context: Context): OkHttpClient {
    return OkHttpClient.Builder()
            .cache(cache)
            .addInterceptor { chain ->
                var request = chain.request()
                request = if (hasNetwork(context)!!)
                    request.newBuilder().header("Cache-Control", "public, max-age=" + 5).build()
                else
                    request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build()
                chain.proceed(request)
            }
            .build()
}

/**
 * Provides the Quotes service implementation.
 * @param retrofit the Retrofit object used to instantiate the service
 * @return the Quote service implementation.
 */
@Provides
@Singleton
fun provideQuotesAPI(retrofit: Retrofit): QuotesAPI {
    return retrofit.create(QuotesAPI::class.java)
}

/**
 * Provides the Retrofit object.
 * @return the Retrofit object
 */
@Provides
@Singleton
fun provideRetrofitInterface(okHttpClient: OkHttpClient): Retrofit {
    return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(MoshiConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
            .client(okHttpClient)
            .build()
}

ViewModelModule

@Module
abstract class ViewModelModule {

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

@Binds
@IntoMap
@ViewModelKey(QuotesListViewModel::class)
internal abstract fun bindsQuotesListViewModel(quotesListViewModel: QuotesListViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(QuoteListItemViewModel::class)
internal abstract fun bindsQuoteListItemViewModel(quoteListItemViewModel: QuoteListItemViewModel): ViewModel

我的申请

class MyApplication : Application(), HasActivityInjector {

@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>

override fun activityInjector(): AndroidInjector<Activity> = dispatchingAndroidInjector

override fun onCreate() {
    super.onCreate()
    // StateSaver.setEnabledForAllActivitiesAndSupportFragments(this, true)

    // initialise dependency injection
    DaggerAppComponent
        .builder()
        .application(this)
        .build()
        .inject(this)

}

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(base)
    MultiDex.install(this)
}

主 Activity

class MainActivity : DaggerAppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

private lateinit var binding: ActivityMainBinding
private lateinit var menu: Menu

override fun onCreate(savedInstanceState: Bundle?) {
    AndroidInjection.inject(this)
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
}
}

最佳答案

终于,经过多次尝试,我发现了我的错误,在AppComponent 我应该调用 MyApplication 类而不是 Application

@Singleton
@Component(
modules = [AndroidSupportInjectionModule::class,
AppModule::class, NetworkModule::class,
ActivityBuilder::class]
)
interface AppComponent : AndroidInjector<MyApplication> {

@Component.Builder
interface Builder {
@BindsInstance
fun application(application: MyApplication): Builder

fun build(): AppComponent
}

关于android - 使用 Dagger 2 注入(inject) Androidx Activity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55760289/

相关文章:

c# - 什么依赖注入(inject)框架与 WebForms

c# - 将您的应用程序容器包含在服务的构造函数中是否被认为是糟糕的 DI 实践?

java - Dagger 2 问题覆盖单个提供来自应用程序使用的库中模块的注释方法

java - 如果时间太长,请重新启动操作

android - 服务和广播接收器之间的区别

database - 从另一个应用程序复制 Android 数据库?

android - android 中的新语言环境(乌尔都语/巴基斯坦)

c# - 在 ASP .Net 3.5 中使用 Ninject 2.0

android - 注入(inject)类如何获得对注入(inject)器的引用?

java - 如何修复 Dagger 2 错误 '... cannot be provided [...]' ?