【问题标题】:Cannot inject object provided in AppModule to Activity in a dynamic feature module with Dagger2无法使用 Dagger2 将 AppModule 中提供的对象注入到动态功能模块中的 Activity
【发布时间】:2020-07-15 06:55:03
【问题描述】:

通过下面的设置,我无法将 Singleton 对象注入到动态功能模块内的 Activity 中。我可以注入到子组件 MainActivity,但不能注入到动态功能模块中的 Activity。

@Component(modules = [AppModule::class])
interface AppComponent {

    fun inject(application: Application)

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance application: Application): AppComponent
    }

    // Types that can be retrieved from the graph
    fun mainActivityComponentFactory(): MainActivitySubComponent.Factory
}

我的应用模块

@Module(includes = [AppProviderModule::class])
abstract class AppModule {

    @Binds
    abstract fun bindContext(application: Application): Context
}

@Module
object AppProviderModule {

    @Provides
    @Singleton
    fun provideSharedPreferences(application: Application): SharedPreferences {
        return application.getSharedPreferences("PrefName", Context.MODE_PRIVATE)
    }
}

动态功能模块库组件

@GalleryScope
@Component(
        dependencies = [AppComponent::class],
        modules = [GalleryModule::class])
interface GalleryComponent {
    fun inject(galleryActivity: GalleryActivity)
}

我的应用程序

open class MyApplication : Application() {

    // Instance of the AppComponent that will be used by all the Activities in the project
    val appComponent: AppComponent by lazy {
        initializeComponent()
    }

    open fun initializeComponent(): AppComponent {
        // Creates an instance of AppComponent using its Factory constructor
        // We pass the applicationContext that will be used as Application
        return DaggerAppComponent.factory().create(this).apply {
            inject(this@MyApplication)
        }
    }
}

动态功能模块中的活动,当仅从GalleryModule 注入GalleryViewerDummyDependency 时,它工作正常

class GalleryActivity : AppCompatActivity() {

    @Inject
    lateinit var sharedPreferences: SharedPreferences

    @Inject
    lateinit var galleryViewer: GalleryViewer

    @Inject
    lateinit var dummyDependency: DummyDependency

    override fun onCreate(savedInstanceState: Bundle?) {

        DaggerGalleryComponent.builder()
                .appComponent((application as MyApplication).appComponent)
                .build()
                .inject(this)

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_gallery)
}

当我尝试从 AppModule 注入 SharedPreferences 或任何不依赖于任何参数(如上下文或应用程序)的依赖项时,我收到错误

error: [Dagger/MissingBinding] android.content.SharedPreferences cannot be provided without an @Provides-annotated method.

【问题讨论】:

  • 我认为你需要在 AppComponent 中公开有趣的 provideSharedPreferences(): SharedPreferences
  • @ErikJhordanRey 它已经包含在 AppComponent 中,如果您希望在模块中同时拥有抽象和静态方法,那么您就是这样做的。我也想出了如何解决它。
  • 我也有同样的问题。解决办法是什么?
  • @PhongBM 我添加了解决方案。你可以检查一下。我在示例应用程序中使用它,效果很好。
  • 我不想像你的演示那样提供 SharedPreferences。我在 AppModule 中提供了许多对象。您还有其他解决方案吗?

标签: android dagger-2 dynamic-feature-module


【解决方案1】:

这里的错误不包括AppComponent中的依赖项的提供方法,并且没有正确构建动态功能组件。

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {

    /**
     * ??? This method is required to get this object from a class that uses this component
     * as dependent component
     */
    fun provideSharedPreferences(): SharedPreferences

    fun inject(application: Application)

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance application: Application): AppComponent
    }

    // Types that can be retrieved from the graph
    fun mainActivityComponentFactory(): MainActivitySubComponent.Factory
}

在动态功能中

@GalleryScope
@Component(
        dependencies = [AppComponent::class],
        modules = [GalleryModule::class])
interface GalleryComponent {

    fun inject(galleryActivity: GalleryActivity)

    // Alternative1 With Builder
    @Component.Builder
    interface Builder {

        fun build(): GalleryComponent

        @BindsInstance
        fun application(application: Application): Builder
        fun galleryModule(module: GalleryModule): Builder

        fun appComponent(appComponent: AppComponent): Builder

    }

    // Alternative2 With Factory
    @Component.Factory
    interface Factory {

        fun create(appComponent: AppComponent,
                   galleryModule: GalleryModule,
                   @BindsInstance application: Application): GalleryComponent


    }
}

您必须使用BuilderFactory,将来可能不需要这些,但是它还不支持动态功能,我宁愿使用工厂模式,因为它们已弃用Builder 模式。

在ActivityonCreate初始化注入

private fun initInjections() {

    // Alternative1 With Builder
    DaggerGalleryComponent.builder()
            .appComponent((application as MyApplication).appComponent)
            .application(application)
            .galleryModule(GalleryModule())
            .build()
            .inject(this)

    // Alternative2 With Factory
    DaggerGalleryComponent
            .factory()
            .create((application as MyApplication).appComponent, GalleryModule(), application)
            .inject(this)

}

您应该选择与特征组件内部使用的相同的模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多