Dagger 2,图书馆模块和@Singleton

时间:2016-11-08 15:06:53

标签: android dagger-2

我尝试在具有多个Android库模块的Android项目中使用Dagger 2,并且我希望能够提供单例范围的实例

目前,我能够在库模块中定义组件,并在主应用程序模块中注入实例。

我无法做的是提供一个单例实例。

项目结构如下:

Project
├── app
├── library1
·
·
·
└── libraryN

在库中,我以这种方式定义组件:

@Component
public interface LibraryComponent {

    // Provide instances of MyManager to MainComponent:
    MyManager getMyManager();
}

MyManager看起来像这样:

public class MyManager {

    private static final String TAG = "MyManager";

    @Inject
    public MyManager() {
        Log.d(TAG, "Creating MyManager");
    }
}

在主App中我以这种方式定义我的组件:

@ApplicationScope
@Component(dependencies = {LibraryComponent.class, Library2Component.class})
public interface MainComponent {

    void inject(MainActivity target);
}

这是Application类:

public class App extends Application {
    private MainComponent component;

    @Override
    public void onCreate() {
        super.onCreate();

        component = DaggerMainComponent.builder()
                .libraryComponent(DaggerLibraryComponent.create())
                .library2Component(DaggerLibrary2Component.create())
                .build();
    }

    public MainComponent getComponent() {
        return component;
    }
}

如果我只将范围添加到一个库组件,那么我可以将管理器作为单例提供。但是,如果我尝试对另外一个库执行相同的操作,我会收到错误:

@com.codeblast.dagger2lib.ApplicationScope com.codeblast.dagger2lib.MainComponent depends on more than one scoped component:
@Component(dependencies = {LibraryComponent.class, Library2Component.class})
^
      @com.codeblast.library.LibraryScope com.codeblast.library.LibraryComponent
      @com.codeblast.library2.Library2Scope com.codeblast.library2.Library2Component

同样,我想要实现的只是在我的主应用程序项目中注入由库项目提供的一些管理器的单例范围实例

2 个答案:

答案 0 :(得分:9)

正如@EpicPandaForce所建议的,使用Dagger模块代替组件解决了我的问题

接下来,我必须做出必要的修改。

第一个是删除库组件并创建库模块:

@Module
public class LibraryModule {

    @Singleton
    @Provides
    MyManager provideMyManager(MyUtility myUtility) {
        return new MyManager(myUtility);
    }
}

不只是在App Component中指定那些模块,而不是组件的依赖项:

@Singleton
@Component(modules = {LibraryModule.class, Library2Module.class})
public interface MainComponent {

    void inject(MainActivity target);
}

就是这样,使用@Singleton范围注释的Manager类在此代码中只能正确实例化一次。

答案 1 :(得分:1)

尝试在单个组件下统一库组件(例如:AllLibrariesComponent),然后让您的MainComponent仅依赖AllLibrariesComponent。

<强>分享帮助

@Component
@Singleton
public interface LibraryComponent {

    // Provide instances of MyManager to MainComponent:
    MyManager getMyManager();

}

@Singleton
public class MyManager {

    private static final String TAG = "MyManager";

    @Inject
    public MyManager() {
        Log.d(TAG, "*** Creating MyManager 1 ***");
    }
}

<强> Library2:

@Singleton
@Component
public interface Library2Component {

    // Provide instances of MyManager to MainComponent:
    MyManager2 getManager2();

}

@Singleton
public class MyManager2 {

    private static final String TAG = "MyManager";

    @Inject
    public MyManager2() {
        Log.d(TAG, "*** Creating MyManager 2 *** ");
    }
}

应用

@Singleton
@Component
public interface AllLibrariesComponent extends Library2Component, LibraryComponent{
}

@PerApplication
@Component(dependencies = AllLibrariesComponent.class)
public interface MainComponent {

    void inject(MainActivity activity);

}

// .... 
// and the instantication in your application class:
mainComponent = DaggerMainComponent.builder()
                .allLibrariesComponent(DaggerAllLibrariesComponent.create())                  
                .build();