Im pretty new in Android development and newer in DI. I am using Kotlin on a personal project where I am experimenting with Dagger 2. I managed to set it up for a util class
You can't use class PineApplication @Inject constructor(): Application()
to create PineApplication
. It's a framework class and has to be created by the Android Framework.
Doing so Dagger will create PineApplication
, but applicationContext
will return null
as it has never been initialized (by the system).
Don't use constructor injection for framework classes and don't create the yourself. Use @Bindsintance
to add the object to the component with its builder, or use a module to provide it.
For provide application context, you can create class, like ComponentsManager
with:
public class ComponentsManager {
private Context context;
private AppComponent appComponent;
public ComponentsManager(Context context) {
this.context = context.getApplicationContext();
}
public AppComponent getAppComponent(){
if (appComponent == null){
appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(context))
.build();
}
return appComponent;
}
}
And in your application class init this ComponentsManager
like this:
public class YourApp extends Application {
private static ComponentsManager componentsManager;
@Override
public void onCreate() {
super.onCreate();
initComponentsManager();
initAppComponent();
}
public static ComponentsManager getComponentsManager(){
return componentsManager;
}
private void initComponentsManager(){
componentsManager = new ComponentsManager(this);
}
private void initAppComponent(){
componentsManager.getAppComponent();
}
}
This is how It is done. Using @BindsInstance in your component will inject application to all of your modules.In your case just to AppModule
@Singleton
@Component(modules = arrayOf(AppModule::class))
interface AppComponent {
@Component.Builder
interface Builder() {
fun build(): AppComponent
@BindsInstance
fun application(application: Application): Builder
}
}
** Delete code to "Provides application" function in your APP module and make sure you pass application context to create sharedPreferences.
@Module
class AppModule {
@Provides
@Singleton
fun provideSharedPrefManager(context: Application): SharedPreferencesManager =
SharedPreferencesManager(context)
}
and now in your onCreate of applicationClass
DaggerAppComponent.builder().application(this).build()
Optional: if you want to inject something into your applicationClass then do the following
DaggerAppComponent.builder().application(this).build().inject(this)
You can try modifying your App module like this.
@Module
class ApplicationModule(private val application: Application) {
@Provides
@Singleton
fun provideContext(): Context {
return application.applicationContext
}
@Provides
@Singleton
fun provideSharedPreferences(context: Context): SharedPreferences {
return context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE)
}
}
Then you can build the dagger component like this from your Application class.
val appComponent = DaggerAppComponent.builder()
.applicationModule(ApplicationModule(this))
.build()
Inject values in presenter like this.
application.appComponent.inject(this)