Dagger 2, Providing Application Context in Module

前端 未结 4 1224
北海茫月
北海茫月 2021-01-13 22:17

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

相关标签:
4条回答
  • 2021-01-13 22:52

    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.

    0 讨论(0)
  • 2021-01-13 22:54

    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();
        }
    }
    
    0 讨论(0)
  • 2021-01-13 22:58

    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)
    
    0 讨论(0)
  • 2021-01-13 23:00

    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)
    
    0 讨论(0)
提交回复
热议问题