I just started using dagger2 and in spite of having read and documented myself to get the main ideas, I don't understand which would be the proper way of injecting the application's context.
I know that there are similar questions like this or this but this uses AndroidInjector and I'm getting even more lost. What I would like to understand is once the ContextComponent has been initialised and is a Singleton, how can I retrieve the instance of ContextComponent (that contains the Application's context) in order to call ContextComponent.getSharedPreferenceSpecific() and get an instance of SharedPreferenceManagerSpecific initialised with the Application's context?
The are the classes I have created, SharedPreferenceManagerSpecific it's just to understand how to inject a context to a class.
The error I get when the code of activity is executed i:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.amgdeveloper.articleReader/com.amgdeveloper.articleReader.ui.MainActivity}: java.lang.IllegalStateException: com.amgdeveloper.articleReader.dagger.ContextModule must be set at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
ContextModule.kt
@Module
class ContextModule(private val app: Application) {
@Provides
@Singleton
fun provideContext(): Context = app
}
ContextComponent.tk
@Singleton
@Component(modules = [ContextModule::class])
interface ContextComponent {
fun getSharedPreferenceSpecific ():SharedPreferenceManagerSpecific
fun inject (application: MyApplication)
fun inject (application: MainActivity)
MyApplication.kt
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
DaggerContextComponent.builder().contextModule(ContextModule(this)).build()
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val component = DaggerContextComponent.builder().build()
val sharedPreference = component.getSharedPreferenceSpecific()
}
}
SharedPreferenceManagerSpecific.kt
public class SharedPreferenceManagerSpecific () {
lateinit var myContext : Context
@Inject constructor( context: Context) : this() {
myContext=context
}
fun saveIntoSharedPreferences(){
...
}
}
Dagger doesn't store component instances anywhere. Not even @Singleton
components: as far as Dagger is concerned, @Singleton
is just another scope. In order to create a component in your Application
class and use it in your Activity
class, you will need to store it somewhere yourself.
In most Android apps using Dagger, the component is stored in the Application
:
class MyApplication : Application() {
// You could set a lateinit var in onCreate instead
// if you don't use any ContentProviders.
val component by lazy {
DaggerContextComponent.builder().contextModule(ContextModule(this)).build()
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val component = (application as MyApplication).component
val sharedPreference = component.getSharedPreferenceSpecific()
}
}