Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
303 views
in Technique[技术] by (71.8m points)

java - Dagger 2: Provide same instance between multiple Component with same Scope on different library modules

I have a Core Android Library where I'm defining a CoreComponent ad using the @Singleton scope to inject instances of classes provided by a CoreModule.

@Singleton
@Component(modules = {CoreModule.class})
public interface CoreComponent {
    void inject(SomeClass target);
}

@Module
public class CoreModule {
    @Singleton
    @Provides
    CoreRepository provideCoreRepository() {
        return new CoreRepositoryImpl();
    }
}

I would like to access the same @Singleton instances from another Android Library that is depending on the Core Library and is using another component.

@Singleton
@FooScope
@Component(modules = {CoreModule.class, FooModule.class})
public interface FooComponent {
    void inject(SomeActivity target);
}

public class FooActivity extends AppCompatActivity {
    @Inject
    public CoreRepository repo;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        injectDependencies();
        super.onCreate(savedInstanceState);
    }
    [...]
}

The code above builds but the @Singleton scope is "local" to the Component. In other words there are two singleton instances, one for the for the CoreComponent and one for the FooComponent.

Android Application
├── Foo Library
|   └── Core Library
├── Bar Library
|   └── Core Library
·
·
·
└── Core Library

I think that the best solution should be using a Subcomponent but, unfortunately, doesn't seem possible because the Core Library has no visibility of the other libraries.

Is there another way to share with Dagger the same instance of one class between components if the class is annotated with the same Scope?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Remove the injection sites from your CoreComponent - it now has the sole function of exposing the binding for CoreRepository to its dependent components:

@Singleton
@Component(modules = {CoreModule.class})
public interface CoreComponent {
    CoreRepository coreRepository();
}

Create a reference to this singleton-scoped component inside your application:

public class MyApplication extends Application {
    private final CoreComponent coreComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        coreComponent = DaggerCoreComponent
                            .coreModule(new CoreModule())
                            .build();
    }

    public static CoreComponent getCoreComponent(Context context) {
        return ((MyApplication) context.getApplicationContext()).coreComponent;
    }
}

Create a new narrower scope:

@Scope
@Retention(RetentionPolicy.RUNTIME) public @interface PerActivity {}

Create a new component that tracks this scope complete with the injection sites you want:

@PerActivity
@Component(dependencies = {CoreComponent.class})
public interface ActivityComponent {
    void inject(FooActivity activity);

    void inject(BarActivity activity);
}

When you access this activity-scoped component in the injection site, you will need to provide the instance of CoreComponent to the builder. Now you can inject into your Activity

public class FooActivity extends AppCompatActivity {
        @Inject
        public CoreRepository repo;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            CoreComponent coreComponent = MyApplication.getCoreComponent(this);
            DaggerActivityComponent.builder()
                .coreComponent(coreComponent)
                .build()
                .inject(this);
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...