Dagger singleton每次创建新实例

Rel*_*elm 6 java android dependency-injection dagger-2

我有一个模块如下.

@Module
public class AppModule {
    private final Application app;

    public AppModule(Application app) {
        this.app = app;
    }

    @Provides
    @Architecture.ApplicationContext
    Context provideContext() {
        return app;
    }

    @Provides //scope is not necessary for parameters stored within the module
    public Context context() {
        return provideContext();
    }

    @Singleton
    @Provides
    Application provideApp() {
        return app;
    }

    @Singleton
    @Provides
    SoundsRepository provideSoundsRepository(Context context, SoundsDAO soundsDAO) {
        return new SoundsRepository(context, soundsDAO);
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样的组件.

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {

    void inject(Global global);

    void inject(MainActivity mainActivity);


    @Architecture.ApplicationContext
    Context getContext();

    Application getApplication();

    void inject(PostView postView);

    void inject(MediaPlayerService mediaPlayerService);
}
Run Code Online (Sandbox Code Playgroud)

在活动,片段或服务中,我这样做

@Inject
    SoundsRepository soundsRepository;

@Override
protected void onCreate(...) {
    //....
    ((Global) getApplication()).getComponent().inject(this);
}
Run Code Online (Sandbox Code Playgroud)

在SoundsRepository中

@Singleton
public class SoundsRepository {
    @Inject
    public SoundsRepository(Context context, SoundsDAO soundsDAO) {
        this.context = context;
        this.soundsDAO = soundsDAO;
        System.out.println(TAG + "INIT");
    }
    // ....

}
Run Code Online (Sandbox Code Playgroud)

所以,现在,每当我开始访问注入SoundsRepository的活动或服务时,我得到一个新实例,我的意思是,"SoundsRepository"的构造函数再次触发.

我究竟做错了什么?

编辑:在应用程序类中注入

public class Global extends MultiDexApplication {

    protected AppComponent appComponent;
    private boolean calledAlready = false;

    @Override
    public void onCreate() {
        super.onCreate();
        //if (LeakCanary.isInAnalyzerProcess(this)) return;
        //LeakCanary.install(this);
        initFirebasePersistance();
        appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
        appComponent.inject(this);
        FrescoUtil.init(getApplicationContext());
    }


    public AppComponent getComponent() {
        return appComponent;
    }
}
Run Code Online (Sandbox Code Playgroud)

Pio*_*r Z 5

  1. 在你的模块,你必须提供SoundsRepository实例的方法 - 好
  2. 在您的AppComponent中,您缺少:

    SoundsRepository soundsRepository();
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在您Global扩展Application / MultidexApplication的位置上,您将创建DaggerAppComponent-很好

  4. 在您的其他活动/片段/服务中,只需致电:

    Global application = (Global) getApplication();
    SoundsRepository sr = application.getComponent().soundsRepository()
    
    Run Code Online (Sandbox Code Playgroud)

Android保证您对所有其他活动/服务仅拥有Application(全局)类的一个实例(有点像单例)。

因此,请将您的组件保留在该应用程序类中,并在需要时调用: (YourApplication) getApplication().getComponent().yourSingleInstanceSomething();

我为您创建并测试了示例代码:https : //github.com/zakrzak/StackDaggerTest

Dagger的@Singleton只是作用域,并不保证返回类的单个实例。

据我了解,如果您:

void inject(PostView postView);
Run Code Online (Sandbox Code Playgroud)

您告诉Dagger,只要使用以下命令,就可以立即在PostView中访问用AppModule中@Provided注释的所有内容:

@Inject
SoundsRepository soundsRepository;
Run Code Online (Sandbox Code Playgroud)

然后匕首只调用@provided方法,在您的情况下,该方法将返回一个新的SoundRepository实例:

@Singleton
@Provides
SoundsRepository provideSoundsRepository(Context ........) {
    return new SoundsRepository(...);
}
Run Code Online (Sandbox Code Playgroud)

导致你的问题