2

I need to @Inject constructor activity and fragmentManager into my Navigator.class. But I'm getting this error:

AppCompatActivity cannot be provided without an @Inject constructor or from an @Provides-annotated method.

I've read all similar questions on Stackoverflow. I did everything they suggested, but didn't find the answer.

Navigator.class

@Singleton
class Navigator @Inject constructor(private val activity: AppCompatActivity,
                                    private val fragmentManager: FragmentManager)

BaseActivity.class

abstract class BaseActivity: AppCompatActivity(), HasSupportFragmentInjector{
    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>
    @Inject
    lateinit var navigator: Navigator
   override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }
override fun supportFragmentInjector() = fragmentInjector

BaseModule.class

@Module
abstract class BaseActivityModule {
@Module
companion object {

    @JvmStatic
    @Provides
    @Named(ACTIVITY_FRAGMENT_MANAGER)
    @PerActivity
    fun activityFragmentManager(activity: AppCompatActivity): FragmentManager =
            activity.supportFragmentManager
}

@Binds
@PerActivity
abstract fun activity(appCompatActivity: AppCompatActivity): Activity

@Binds
@PerActivity
abstract fun activityContext(activity: Activity): Context

MainActivityModule.class

@Module(includes = [
    BaseActivityModule::class

])
abstract class MainActivityModule {

    @Binds
    @PerActivity
    abstract fun appCompatActivity(mainActivity: MainActivity): AppCompatActivity

AppModule.class

    @Module(includes = [AndroidSupportInjectionModule::class])
abstract class AppModule {
@Binds
@Singleton
abstract fun application(app: App): Application

@PerActivity
@ContributesAndroidInjector(modules = [MainActivityModule::class])
abstract fun mainActivityInjector(): MainActivity
user1892364
  • 259
  • 2
  • 12
Toper
  • 263
  • 5
  • 17

1 Answers1

0

First, please make sure to understand what the error means. You're trying to inject AppCompatActivity but Dagger complains that it cannot be provided. So far so good. Please always make sure to include the full error as shown in the link, so that we can more easily see what's going on. In your case this seems to be a scoping issue.

You provide a Navigator through constructor injection as a @Singleton...

@Singleton
class Navigator @Inject constructor(private val activity: AppCompatActivity,
                                private val fragmentManager: FragmentManager)

And you provide/bind AppCompatActivity from a module with @PerActivity scope.

@Binds
@PerActivity
abstract fun appCompatActivity(mainActivity: MainActivity): AppCompatActivity

So unless you have a really crazy setup, @Singleton will not be able to access @PerActivity. If it could, you'd have a memory leak at the very least, since you'd keep your Activity instance around longer than its lifetime (onCreate -> onDestroy)


To solve your problem you have to either move Navigator down in scope to also be @PerActivity and share the lifecycle of the Activities it references (so that it won't leak) or you have to remove the dependency on your Activity in your constructor. If you really do need it to be @Singleton and reference an Activity you might be able to have a setter for the current Activity, but again, watch out for leaks.

David Medenjak
  • 33,993
  • 14
  • 106
  • 134
  • Thanks, it works, but i also had problem with `@Named(ACTIVITY_FRAGMENT_MANAGER)` , so i removed this annotation and now everything is fine – Toper Jul 03 '18 at 08:35