From the dagger 2 Documentation I noticed that you can have a @Singleton
annotated class. What is the purpose of marking a class as @Singleton
as I hav
What is singleton?
Singleton Pattern in android
A single instance of a class providing a global point of access to itself during the entire application's lifetime.
@Singleton annotation in Dagger
A single instance of a class which is unique to a specific component, its access is limited to the scope of the component.
Purpose of singleton
To provide a single instance of a class within the dependency graph(component). a component is usually initialized in the application level as it executes only ones for the entire applications lifetime and is accessible by all activities and fragment.
Let's take an example:
CoffeeComponent.kt
@Singleton
@Component
interface CoffeeComponent {
fun getCoffeeMaker():CoffeeMaker
fun inject(activityA: ActivityA)
fun inject(activityB: ActivityB)
}
CoffeeMaker.kt
@Singleton
class CoffeeMaker @Inject constructor()
CoffeeAplication.kt
class CoffeeApplication : Application() {
private val component by lazy {
DaggerCoffeeComponent.builder().build()
}
fun getAppComponent(): CoffeeComponent = component
}
Recommended Practise
Always go for lazy initialization of your component.
Scenario: say, you are team decided to add an onboarding/tutorial screen or incorporate some other design which doesn't require the component during the initial screens, it will help minimize the startup delay. Always remember, component initialization is expensive.
ActivityA.kt
import dagger.Lazy
class ActivityA: AppCompatActivity() {
@Inject
lateinit var coffeeMaker1:Lazy
@Inject
lateinit var coffeeMaker2:Lazy
private val component by lazy {
(application as CoffeeApplication).getAppComponent()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_activityB.setOnClickListener { startActivity(Intent(this, NewActivity::class.java)) }
component.inject(this)
println("Activity A CoffeeMaker 1 - ${coffeeMaker1.get()}")
println("Activity A CoffeeMaker 2 - ${coffeeMaker2.get()}")
}
}
If your class is expensive to construct, use the dagger's Lazy initialization, please don't confuse it with kotlin's Lazy. You have to import
import dagger.Lazy
@Inject
lateinit var coffeeMaker1:Lazy
ActivityB.kt
class ActivityB: AppCompatActivity() {
@Inject
lateinit var coffeeMaker1:Lazy
@Inject
lateinit var coffeeMaker2:Lazy
private val component by lazy {
(application as CoffeeApplication).getAppComponent() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new)
component.inject(this)
println("Activity B CoffeeMaker 1 - ${coffeeMaker1.get()}")
println("Activity B CoffeeMaker 2 - ${coffeeMaker2.get()}")
}
}
you will get the Log output as
Note:
If you want to share a singleton instance between activities, lazily initialize them in the application level, if you initialize them in an activity you will end up with different instance as the components are different