首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有Dagger和AndroidInjectors的子模块

带有Dagger和AndroidInjectors的子模块
EN

Stack Overflow用户
提问于 2019-07-05 07:36:10
回答 1查看 1.1K关注 0票数 3

我已经做了一段时间前Android喷射器风格的匕首,现在我决定尝试新的方法。直到现在,我基本上是这样在AppComponent上声明的:

代码语言:javascript
运行
复制
@Singleton
@Component(
        modules = [ApplicationModule::class,
            NetModule::class,
            ApiModule::class,
            AnalyticsModule::class,
            DbModule::class,
            RepositoryModule::class,
            InteractorModule::class]
)
interface ApplicationComponent {
    fun inject(app: MyApp)
    fun plus(controllerModule: ControllerModule): ControllerComponent
}

然后我会像这样注射我的Activities/Fragments/Services/Dialogs

代码语言:javascript
运行
复制
class MyActivity : AppCompatActivity() {
...
    val component by lazy {
            (application as MyApp)
                    .applicationComponent
                    .plus(
                            ControllerModule(this)
                    )
        }

    override fun inject() {
            component.inject(this)
        }
...
}

基本上,我有一个带有应用程序遍历模块的顶级应用程序组件,然后是一个具有每个活动实例的活动级组件(ControllerComponent),这是所有活动所共有的。

现在我切换到了新方法,我创建了如下所示的组件:

代码语言:javascript
运行
复制
@Singleton
@Component(
        modules = [
            AndroidSupportInjectionModule::class,
            AppModule::class,
            NetModule::class,
            ApiModule::class,
            AnalyticsModule::class,
            DbModule::class,
            RepositoryModule::class,
            InteractorModule::class
        ]
)
interface AppComponent : AndroidInjector<SoulpicksApp> {

    @Component.Builder
    interface Builder {
        fun build(): AppComponent
        @BindsInstance
        fun application(application: SoulpicksApp): Builder
    }

}

让我的应用程序扩展DaggerApplication

代码语言:javascript
运行
复制
open class MyApp : DaggerApplication() {


    override fun applicationInjector(): AndroidInjector<out DaggerApplication> = DaggerAppComponent.builder().application(this).build()

}

我的Activities/Fragments分别扩展了DaggerAppCompatActivty/DaggerFragment

代码语言:javascript
运行
复制
class MyActivity : DaggerAppCompatActivity() {

...
}

我理解这应该会自动连接所有的活动依赖关系,只要Dagger被正确设置。然而,我并没有声明我的ControllerModule/Component,所以在运行我的应用程序时,我当然会得到:

代码语言:javascript
运行
复制
e: /Users/user/dev/my-android/app/build/generated/source/kapt/devDebug/com/myapp/android/di/activity/ActivityBinder_ContributesMyActivity.java:28: error: @Subcomponent.Builder is missing setters for required modules or subcomponents: [com.myapp.android.di.controller.ControllerModule]

我以前了解到,我是通过使用plus()方法并显式地注入(这正是我在这里试图避免的)在每个Activity上创建这个组件的,我现在该怎么做呢?

另外,我的应用程序中有一些BottomSheetDialogFragmentsJobServiceIntents,没有相应的DaggerBottomSheedDialogFragments/DaggerJobServiceIntents可供扩展,我该如何解决这个问题呢?

ControllerModule:

代码语言:javascript
运行
复制
@Module
class ControllerModule(val activity: androidx.fragment.app.FragmentActivity) {

    @Provides
    @ControllerScope
    fun context(): Context = activity

    @Provides
    @ControllerScope
    fun activity() = activity

    @Provides
    @ControllerScope
    fun layoutInflater() = activity.layoutInflater

    @Provides
    @ControllerScope
    fun fragmentManager(): androidx.fragment.app.FragmentManager = activity.supportFragmentManager

    @Provides
    @ControllerScope
    fun provideNavigationController(activity: androidx.fragment.app.FragmentActivity, analyticsManager: AnalyticsCompositeManager) = NavigationController(activity, analyticsManager)

    @Provides
    @ControllerScope
    fun providePackageUtils(activity: androidx.fragment.app.FragmentActivity) : PackageUtils = PackageUtilsImpl(activity)
}

@luis_cortes应答后的更改:

封装io.soulpicks.android.di.activity

代码语言:javascript
运行
复制
@Module
abstract class ActivityBinder {

    @ControllerScope
    @ContributesAndroidInjector(modules = [ControllerModule::class])
    abstract fun constributesSplashActivity(): SplashActivity

    @ControllerScope
    @ContributesAndroidInjector(modules = [ControllerModule::class])
    abstract fun contributesDashboardActivity(): DashboardActivity

    ....


}

ControllerModule:

代码语言:javascript
运行
复制
@Module(includes = [ViewContainerModule::class])
class ControllerModule {


    @Provides
    @ControllerScope
    fun context(activity: DaggerAppCompatActivity): Context = activity.applicationContext

    @Provides
    @ControllerScope
    fun layoutInflater(activity: DaggerAppCompatActivity) : LayoutInflater = activity.layoutInflater

    @Provides
    @ControllerScope
    fun fragmentManager(activity: DaggerAppCompatActivity): FragmentManager = activity.supportFragmentManager

    @Provides
    @ControllerScope
    fun navigationController(activity: DaggerAppCompatActivity, analyticsManager: AnalyticsCompositeManager): NavigationController = NavigationController(activity, analyticsManager)

    @Provides
    @ControllerScope
    fun providePackageUtils(activity: DaggerAppCompatActivity): PackageUtils = PackageUtilsImpl(activity)
}

错误:

代码语言:javascript
运行
复制
e: /Users/kelmer/dev/myapp-android/app/build/tmp/kapt3/stubs/devDebug/io/myapp/android/di/application/AppComponent.java:8: error: [Dagger/MissingBinding] com.myapp.android.managers.PackageUtils cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.myapp.android.MyApp> {
                ^
      com.myapp.android.managers.PackageUtils is injected at
          com.myapp.android.ui.invite.SendInviteViewModel(packageUtils, …)
      com.myapp.android.ui.invite.SendInviteViewModel is injected at
          com.myapp.android.di.viewmodel.ViewModelModule.sendInviteViewModel$app_devDebug(sendInviteViewModel)
      java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
          com.myapp.android.di.viewmodel.MyappViewModelFactory(viewModels)
      com.myapp.android.di.viewmodel.MyappViewModelFactory is injected at
          com.myapp.android.di.viewmodel.ViewModelModule.bindViewModelFactory$app_devDebug(factoryMyapp)
      androidx.lifecycle.ViewModelProvider.Factory is injected at
          com.myapp.android.base.BaseActivity.viewModelFactory
      com.myapp.android.ui.splash.SplashActivity is injected at
          dagger.android.AndroidInjector.inject(T) [com.myapp.android.di.application.AppComponent → com.myapp.android.di.activity.ActivityBinder_ConstributesSplashActivity.SplashActivitySubcomponent]
  It is also requested at:
      com.myapp.android.ui.dashboard.friends.contact.ContactSyncViewModel(…, packageUtils, …)
      com.myapp.android.views.appchoosedialog.AppChooserViewModel(packageUtils)
  The following other entry points also depend on it:
      dagger.android.AndroidInjector.inject(T) [com.myapp.android.di.application.AppComponent → com.myapp.android.di.activity.ActivityBinder_ContributesDashboardActivity.DashboardActivitySubcomponent]

https://github.com/kelmer44/mvvm-base

分支master是当前的实现(没有匕首-android)分支chore/dagger-rework是我的尝试。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-08 18:49:20

更新

我设法让示例项目对原始解决方案进行了一些非常小的调整。我已经更新了下面的答案,为后人和标记步骤是新的或已更改的粗体。

注意:在样例项目中对ControllerModule有一些非常小的必要调整,但下面的答案将最适用于站点上的其他人,所以我选择在这里省略它们。

  • MainActivityModule 创建一个名为的文件,其中包含以下内容:
代码语言:javascript
运行
复制
@Module
abstract class MainActivityModule {
   @Binds @ControllerScope
   abstract fun bindsActivity(mainActivity: MainActivity): FragmentActivity
}
  • 将其添加到安装在AppComponent:上的模块中
代码语言:javascript
运行
复制
@ContributesAndroidInjector([ControllerModule::class, MainActivityModule::class])
@ControllerScope 
abstract fun contributesMyActivity(): MyActivity
  • val activity: androidx.fragment.app.FragmentActivity作为ControllerModule构造函数的属性删除
  • 更改您的@Provides方法以接受如下所示的FragmentActivity
代码语言:javascript
运行
复制
@Provides
@ControllerScope
fun providesContext(activity: FragmentActivity): Context = activity

对于其他类,它只取决于您是否控制它们何时以及如何被实例化。如果需要,只需使用常规构造函数注入即可。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56898569

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档