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.
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}")
}
}