Search code examples
androiddagger-2

Dagger 2 Singleton between Android Activities


I am trying to understand how @Singleton works on Dagger 2

build.gradle

implementation 'com.google.dagger:dagger:2.32'
kapt 'com.google.dagger:dagger-compiler:2.32'

Vehicle.kt

@Singleton
class Vehicle @Inject constructor() {

    var speed = 0
}

AppComponent.kt

@Singleton
@Component
interface AppComponent {

    fun inject(activity: MainActivity)

    fun inject(activity: SecondActivity)
}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var mVehicle: Vehicle

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        DaggerAppComponent.create().inject(this)

        mVehicle.speed = 75
    }
}

SecondActivity.kt

class SecondActivity : AppCompatActivity() {

    @Inject
    lateinit var mVehicle: Vehicle

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        DaggerAppComponent.create().inject(this)

        Log.d(TAG, "Vehicle speed: ${mVehicle.speed}")
    }
}

I expect to see the Vehicle speed 75 on SecondActivity, but it is 0. I am sure there must be something I am missing or misunderstand, just cannot figure it out.


Solution

  • The problem is based on the fact you're creating multiple instances of DaggerAppComponent. You have to create a component once, store it somewhere (object, Application), and then use it for injection. Every instance of the component represents a complete, independent dependency graph.

    Something like this should work as expected:

    @Singleton
    @Component
    interface AppComponent {
        fun inject(activity: FirstActivity)
        fun inject(activity: SecondActivity)
    }
    
    object ComponentHolder {
        val component: AppComponent by lazy { DaggerAppComponent.create() }
    }
    
    class FirstActivity : AppCompatActivity() {
    
        @Inject lateinit var mVehicle: Vehicle
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            ComponentHolder.component.inject(this)
    
            mVehicle.speed = 75
        }
    }
    
    class SecondActivity : AppCompatActivity() {
    
        @Inject lateinit var mVehicle: Vehicle
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            ComponentHolder.component.inject(this)
            
            Log.d("SecondActivity", "Vehicle speed: ${mVehicle.speed}")
        }
    }