0

I am trying to achieve the following behavior:

  • Use an object provided by a module under a singleton scope in another module with a different scope.

Here is what I have. I have tried a lot of changes based on several answers but I still cannot solve this issue.

The first module (Should be bound to the application's lifecycle)

@Module
public class AModule {

private Context context;

public AModule(Context context) {
   this.context = context;
}    

@Provides
@Singleton
MySharedPreference provideMySharedPreference(SharedPreferences prefs) {
   return new MySharedPreferences(prefs);
}

@Provides
@Singleton
SharedPreference provideSharedPreference() {
   return context.getSharedPreferences("prefs", 0);
}

It's component

@Component(modules = AModule.class)
@Singleton
public interface AComponent {
   void inject(...);
}

The second module (bounded to Activity Lifecycle)

@Module
public class BModule {

   @Provides
   @ActivityScope
   X provideX(MySharedPreferences prefs) {
      return new Y(prefs);
   }
}

It's component

@Component(modules = BModule.class)
@ActivityScope
public interface BComponent {
   Y Y();
}

I declared the Activity Scope

@Scope
@Retenion(RetentionPolicy.RUNTIME)
public @interface ActivityScope{}

And MySharedPreferences is as follows

public class MySharedPreferences {

   private SharedPreferences mSharedPrefs;

   @Inject
   public MySharedPreferences(SharedPreferences prefs) {
      mSharedPrefs = prefs;
   }

   // some methods
}

Finally, in my application class, I create the A Component

aComponent = DaggerAComponent.builder().aModule(new AModule(getApplicationContext())).build();

EDIT Some of the things I tried

I tried adding includes = AModule.class to the BModule. I tried adding dependencies = AComponent.class to the BComponent. I tried creating a new Component with the ActivityScope annotation.

T-D
  • 373
  • 8
  • 21

1 Answers1

1

If you are using dependent components (dependencies =) you need to write a provision method to expose the dependency from the @Singleton scoped component to the @ActivityScope component.

@Component(modules = AModule.class)
@Singleton
public interface AComponent {
   void inject(...);

   SharedPreferences exposeSharedPreferences();
}

The provision method will allow the dependent @ActivityScope component to use @Singleton binding for SharedPreferences:

@Component(modules = BModule.class, dependencies = AComponent.class)
@ActivityScope
public interface BComponent {
   Y Y();
}

See this question for a more detailed explanation of provision methods.

David Rawson
  • 20,912
  • 7
  • 88
  • 124
  • Thanks for your answer! Now I understand. I had actually tried something similar to solve the issue but now it is much clearer. – T-D Aug 29 '17 at 00:40