Dagger 2.24 Компонент с зависимостью выдает ошибку: фабрика инжекторов не привязана к классу - PullRequest
0 голосов
/ 17 октября 2019

Итак, я настроил проект с фрагментом SelfInjecting NavHost, основным компонентом приложения и компонентом DataListItems, который зависит от основного компонента приложения. Но у меня кошмар с удовлетворением зависимости от кинжала. Я перенес свою структуру зависимостей из более старого стиля реализации Dagger, который работал нормально, но теперь у меня есть проблемы.

class BaseArchCompApplication : Application(), HasAndroidInjector {

    @Inject
    lateinit var activityInjector: DispatchingAndroidInjector<Any>

    override fun androidInjector() = activityInjector


    override fun onCreate() {
        super.onCreate()


        // init application component.
        DaggerBaseArchCompApplicationComponent.builder().application(this).build()
            .inject(this)

    }

**===========================Component and Modules with AppScope================**

@AppScope
@Singleton
@Component(modules = [AndroidInjectionModule::class, NavHostModule::class, BaseArchCompApplicationModule::class, DataModule::class, NetworkModule::class,
                        RestServiceModule::class, GsonModule::class, RxModule::class])
interface BaseArchCompApplicationComponent : AndroidInjector<Any> {

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

        fun build(): BaseArchCompApplicationComponent
    }

    fun inject(baseArchCompApplication: BaseArchCompApplication){
        val applicationComponent = DaggerBaseArchCompApplicationComponent.builder()
            .application(baseArchCompApplication)
            .build()

        applicationComponent.inject(baseArchCompApplication)
    }

    fun context(): Context

    fun picasso(): Picasso

    fun environmentparameters(): EnvironmentParameters

    fun preferencesmanager(): PreferencesManager

    fun rxSchedulers(): AndroidRxSchedulers

    fun dataService(): DataService

    fun dataListItemsRepository(): DataListItemsRepository

}
==========================

@Module
class BaseArchCompApplicationModule {

    @AppScope
    @Provides
    fun provideContext(baseArchCompApplication: BaseArchCompApplication) = baseArchCompApplication.applicationContext

}

================================

@Module
class DataModule {

    @AppScope
    @Provides
    fun dataListItemsRepository(
        appRemoteDataSource: DataListItemRemoteDataSource,
        appLocalDataSource: DataListItemsLocalDataSource
    ): DataListItemsRepository {
        return DefaultDataListItemsRepository(appRemoteDataSource, appLocalDataSource)
    }

    @AppScope
    @Provides
    fun createDataListItemRemoteDataSource(
        appDatabase: BaseArchCompAppDatabase,
        dataService: DataService
    ): DataListItemRemoteDataSource {
        return DataListItemRemoteDataSource(appDatabase.dataListItemDao(), dataService)
    }

    @AppScope
    @Provides
    fun createDataListItemLocalDataSource(
        appDatabase: BaseArchCompAppDatabase
    ): DataListItemsLocalDataSource {
        return DataListItemsLocalDataSource(appDatabase.dataListItemDao())
    }

    @AppScope
    @Provides
    fun createDataBase(context: Context): BaseArchCompAppDatabase {
        return Room.databaseBuilder(
            context.applicationContext,
            BaseArchCompAppDatabase::class.java, "DataListItems.db"
        ).build()
    }

}
============================


@Module
class RestServiceModule {

    @AppScope
    @Provides
    fun retrofit(
        okHttpClient: OkHttpClient,
        gson: Gson,
        androidSchedulers: AndroidRxSchedulers,
        environmentParameters: EnvironmentParameters
    ): Retrofit {
        return Retrofit.Builder()
            .baseUrl(environmentParameters.baseURL)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(androidSchedulers.network()))
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(okHttpClient)
            .build()
    }


    @AppScope
    @Provides
    fun dataService(retrofit: Retrofit): DataService {
        return retrofit.create(DataService::class.java)
    }

}

==========================================

@Module
class NavHostModule {

    @AppScope
    @Provides
    fun injectingNavHostFragment(): InjectingNavHostFragment {
        return InjectingNavHostFragment()
    }
}

**=============Component and Modules with DataListItemsScope==========**

@DataListItemsScope
@Component(modules = arrayOf(AndroidInjectionModule::class, DataListItemsModule::class), dependencies = arrayOf(BaseArchCompApplicationComponent::class))
interface DataListItemsActivityComponent {
    fun inject(dataListItemsActivity: DataListItemsActivity)
}

===============================

@Module
class DataListItemsModule {

    @DataListItemsScope
    @Provides
    fun dataListItemsViewModel(dataListItemsRepository: DataListItemsRepository, dataService: DataService, preferencesManager: PreferencesManager, picasso: Picasso): DataListItemsViewModel {
        return DataListItemsViewModel(dataListItemsRepository)
    }

    @DataListItemsScope
    @Provides
    fun dataListItemsFragment( picasso: Picasso, preferencesManager: PreferencesManager, viewModel: DataListItemsViewModel): DataListItemsFragment {
        return DataListItemsFragment(viewModel)
    }

    @DataListItemsScope
    @Provides
    fun navHostFragment() : InjectingNavHostFragment{
        return InjectingNavHostFragment()
    }

}

=================================

class DataListItemsActivity : DaggerAppCompatActivity() {

    private lateinit var drawerLayout: DrawerLayout
    private lateinit var appBarConfiguration: AppBarConfiguration

    @Inject
    lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>

    @Inject
    lateinit var dataListItemsViewModel: DataListItemsViewModel

    @Inject
    lateinit var dataListItemsFragment: DataListItemsFragment

    @Inject
    lateinit var dataListItemsRepository: DataListItemsRepository

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.data_items_act)
        setupNavigationDrawer()
        setSupportActionBar(findViewById(R.id.toolbar))


        DaggerDataListItemsActivityComponent.builder()
            .dataListItemsModule(DataListItemsModule())
            .build().inject(this)

        val navController: NavController = findNavController(R.id.nav_host_fragment)
        appBarConfiguration =
            AppBarConfiguration.Builder(R.id.dataListItems_fragment_dest)
                .setDrawerLayout(drawerLayout)
                .build()
        setupActionBarWithNavController(navController, appBarConfiguration)
        findViewById<NavigationView>(R.id.nav_view)
            .setupWithNavController(navController)
    }

    override fun onSupportNavigateUp(): Boolean {
        return findNavController(R.id.nav_host_fragment).navigateUp(appBarConfiguration)
            || super.onSupportNavigateUp()
    }

    private fun setupNavigationDrawer() {
        drawerLayout = (findViewById<DrawerLayout>(R.id.drawer_layout))
            .apply {
                setStatusBarBackground(R.color.colorPrimaryDark)
            }
    }
}

Когда я компилирую, я получаю

**java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mycompany.base_arch_comp_app.mock/com.mycompany.base_arch_comp_app.datalistitem.DataListItemsActivity}: java.lang.IllegalArgumentException: No injector factory bound for Class<com.mycompany.base_arch_comp_app.datalistitem.DataListItemsActivity>**
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     **Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class<com.mycompany.base_arch_comp_app.datalistitem.DataListItemsActivity>**
        at dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:136)
        at dagger.android.AndroidInjection.inject(AndroidInjection.java:181)
        at dagger.android.AndroidInjection.inject(AndroidInjection.java:55)
        at dagger.android.support.DaggerAppCompatActivity.onCreate(DaggerAppCompatActivity.java:41)
        at com.mycompany.base_arch_comp_app.datalistitem.DataListItemsActivity.onCreate(DataListItemsActivity.kt:60)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

I am generally having a problem as most of the examples if not all seems to deal with the basic case of a simple Main Activity and a Detailed activity, without any dependencies between the components, so they get away with something like

@Subcomponent (
    modules = [
        DetailFragmentModule::class
    ]
)
interface DetailActivityComponent: AndroidInjector<DetailActivity> {
    @Subcomponent.Factory
    interface Factory : AndroidInjector.Factory<DetailActivity>
}

@Module(subcomponents = [
    DetailActivityComponent::class
])
abstract class DetailActivityModule {
    @Binds
    @IntoMap
    @ClassKey(DetailActivity::class)
    internal abstract fun bindDetailActivityFactory(factory: DetailActivityComponent.Factory): AndroidInjector.Factory<*>
}

Что звучит хорошо довы вводите зависимости от основного компонента приложения и все @Provides от самого компонента Detail

...