2

I am trying to learn dependency injection using Dagger2. I have created few custom scopes and Qualifier. I have created an application component where I wanted to inject certain global dependencies and also I have created an Activity component which will return certain instances based upon activity context.

Now when I try to inject global instances in the Activity I am getting error as follows:

e: /home/arifur/source_code/me/myprojects/Learn/studio/Android/kotlin/FirebaseChat/app/build/tmp/kapt3/stubs/debug/com/example/arifur/firebasechatkotlin/dependecies/component/ActivityComponent.java:7: error: com.google.firebase.auth.FirebaseAuth cannot be provided without an @Provides- or @Produces-annotated method. e:

e: public abstract void inject(@org.jetbrains.annotations.NotNull() e:
^ e: com.google.firebase.auth.FirebaseAuth is injected at e:
com.example.arifur.firebasechatkotlin.BaseActivity.firebaseAuth e:
com.example.arifur.firebasechatkotlin.MainActivity is injected at e:
com.example.arifur.firebasechatkotlin.dependecies.component.ActivityComponent.inject(p0)

w: warning: The following options were not recognized by any processor: '[kapt.kotlin.generated]' w:

e: /home/arifur/source_code/me/myprojects/Learn/studio/Android/kotlin/FirebaseChat/app/src/main/java/com/example/arifur/firebasechatkotlin/BaseActivity.kt: (29, 9): Unresolved reference: DaggerActivityComponent e: /home/arifur/source_code/me/myprojects/Learn/studio/Android/kotlin/FirebaseChat/app/src/main/java/com/example/arifur/firebasechatkotlin/FirebaseChatApp.kt: (20, 13): Unresolved reference: DaggerFirebaseComponent e: /home/arifur/source_code/me/myprojects/Learn/studio/Android/kotlin/FirebaseChat/app/src/main/java/com/example/arifur/firebasechatkotlin/MainActivity.kt: (1, 1): Some error(s) occurred while processing annotations. Please see the error messages above.


Qualifiers

ActivityContext.kt

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ActivityContext

ApplicationContext.kt

@javax.inject.Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ApplicationContext

Scopes

ActivityScope.kt

@Scope
@Retention(AnnotationRetention.SOURCE)
annotation class ApplicationScope

ApplicationScope.kt

@Scope
@Retention(AnnotationRetention.SOURCE)
annotation class ApplicationScope

Components

ActivityComponent.kt Used in Injecting Activity class.

@ActivityScope
@Component(modules = arrayOf(ActivityModule::class), dependencies = arrayOf(FirebaseComponent::class))
interface ActivityComponent {
    fun inject(mainActivity: MainActivity)
}

FirebaseComponent.kt Used in injecting Application class.

@ApplicationScope
@Component(modules = arrayOf(ApplicationModule::class, FirebaseAuthModule::class, NetworkModule::class))
interface FirebaseComponent {
    fun inject(app: FirebaseChatApp)
}

Modules

ActivityModule.kt

@Module
class ActivityModule(val activity : Activity) {
    var mActivityRef : WeakReference<Activity> ;
    init {
        mActivityRef = WeakReference<Activity>(activity)
    }

    @Provides
    @ActivityScope
    @ActivityContext
    public fun getActivityContext() : Context? = mActivityRef.get()

    @Provides
    @ActivityScope
    @ActivityContext
    public fun getActivityInstance() : Activity? = mActivityRef.get();


    @Provides
    @ActivityScope
    public fun getGlideActivityInstance(@ActivityContext context : Context?) : Glide {
        Log.i("activityModule", "Returning activity glide")
        return Glide.get(context);
    }

}

ApplicationModule.kt

@Module
class ApplicationModule(val app : FirebaseChatApp) {

    @ApplicationContext
    @ApplicationScope
    @Provides
    fun provideContext() : Context = app


    @ApplicationInstance
    @ApplicationScope
    @Provides
    fun provideApplication() : Application = app
}

FirebaseAuthModule.kt

@Module
class FirebaseAuthModule {

    @Provides
    @ApplicationScope
    public fun getFirebaseAuth() : FirebaseAuth = FirebaseAuth.getInstance()
}

NetworkModule.kt

@Module
class NetworkModule {

    @Provides
    @ApplicationScope
    public fun getGlideApplicationInstance(@ApplicationContext applicationContext: Context ) : Glide {
        return Glide.get(applicationContext);
    }
}

FirebaseChatApp.kt An Application Class

class FirebaseChatApp : Application() {

        val firebaseComponent: FirebaseComponent by lazy {
            DaggerFirebaseComponent
                    .builder()
                    .applicationModule(ApplicationModule(this))
                    .build()
        }

    @Inject
    lateinit var firebaseAuth : FirebaseAuth

    @Inject
    lateinit var glide : Glide


    override fun onCreate() {
        super.onCreate()
        firebaseComponent.inject(this)
        Log.i("application", "APP->Firebase Auth = " + firebaseAuth)
        Log.i("application", "APP->Glide = " + glide)
    }

    public fun getApplicationComponent() : FirebaseComponent = firebaseComponent;
}

BaseActivity.kt Super classes for all activities

public abstract class BaseActivity : AppCompatActivity(){
    @Inject
    @ActivityScope
    protected lateinit var glide : Glide

    @Inject
    @ApplicationScope
    protected lateinit var firebaseAuth : FirebaseAuth //ERROR HERE

    protected val activityComponent: ActivityComponent by lazy {
        DaggerActivityComponent
                .builder()
                .activityModule(ActivityModule(this))
                .firebaseComponent((this.application as FirebaseChatApp).getApplicationComponent())
                .build()
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        injectComponent(activityComponent)
    }
     abstract fun injectComponent(activityComponent: ActivityComponent)
}

MainActivity.kt Where Objects should get Injected.

class MainActivity : BaseActivity() {


    override fun injectComponent(activityComponent: ActivityComponent) {
        activityComponent.inject(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)
    }
}

What should I do to resolve this error. And what is the correct way of using DI. Since I am new to it. I am getting little confused.

a.r.
  • 565
  • 1
  • 6
  • 18
  • Possible duplicate of [How do I fix Dagger 2 error '... cannot be provided \[...\]'?](https://stackoverflow.com/questions/44912080/how-do-i-fix-dagger-2-error-cannot-be-provided) – David Medenjak Jul 04 '17 at 21:13

1 Answers1

1

The problem is that you are trying to use component dependencies, but you've skipped adding the provision methods that your subscoped component can inherit.

@ApplicationScope
@Component(modules = arrayOf(ApplicationModule::class, FirebaseAuthModule::class, NetworkModule::class))
interface FirebaseComponent {
    fun firebaseAuth() : FirebaseAuth // <-- this is missing

    fun inject(app: FirebaseChatApp)
}
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • e: /home/arifur/source_code/me/myprojects/Learn/studio/Android/kotlin/FirebaseChat/app/build/tmp/kapt3/stubs/debug/com/example/arifur/firebasechatkotlin/dependecies/component/ActivityComponent.java:8: error: com.google.firebase.auth.FirebaseAuth cannot be provided without an @Provides-annotated method. – a.r. Jul 06 '17 at 14:17
  • If I remove dependencies and add modules in the module array. I am getting error related to not able to mix scopes – a.r. Jul 06 '17 at 14:17
  • Are you getting the `FirebaseAuth cannot be provided` error even **after** adding the method I specified in the answer? – EpicPandaForce Jul 06 '17 at 14:22
  • Sorry. My mistake. I have put it in activity component. Thank you :) – a.r. Jul 06 '17 at 14:41