如何将Activity注入正在注入Activity的对象?

时间:2016-03-04 17:15:51

标签: android dependency-injection dagger-2

我有这个模块:

@Module
public class UserProfileModule {

    @Provides
    @Singleton
    UserProfileController providesUserProfileController() {
        return new UserProfileController();
    }

}

和这个组件:

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

    void inject(UserProfileActivity activity);

}

到目前为止,在我的UserProfileActivity我可以@InjectUserProfileController。但现在,我需要将UserProfileActivity注入控制器。我的意思是,互相注入。

我可以通过在UserProfileController UserProfileActivity中调用setActivity(this);设置器来完成此操作,但如果可以自动设置则会很好。

如何实现?

感谢。

1 个答案:

答案 0 :(得分:2)

For starters: add it to the constructor. Then declare that dependency.

@Provides
@Singleton
UserProfileController providesUserProfileController(UserProfileActivity activity) {
    return new UserProfileController(activity);
}

After doing so dagger will complain about not being able to provide UserProfileActivity unless you already do so. If you don't, add another module, or just provide the dependency from that same module. The actual implementation follows, first we need to fix your code.

@Singleton is a dependency on top of the hierarchy. You can't—or at least should not—have an activity dependency for a @Singleton annotated object, since this will probably cause bad smells and/or memory leaks. Introduce a custom scope @PerActivity to use for dependencies within your activities lifespan.

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

This will allow for correct scoping of the object. Please also refer to some tutorials about dagger, since this is a really important issue and covering everything in a single answer would be too much. e.g. Tasting dagger 2 on android

The following uses the latter approach of the aforementioned 2 options by expanding your module:

@Module
public class UserProfileModule {

    private final UserProfileActivity mActivity;

    public UserProfileModule(UserProfileActivity activity) {
        mActivity = activity;
    }

    @Provides
    @PerActivity
    UserProfileActivity provideActivity() {
        return mActivity;
    }

    @Provides // as before
    @PerActivity
    UserProfileController providesUserProfileController(UserProfileActivity  activity) {
        return new UserProfileController(activity);
    }

}

If you now use your component Builder you can create a new instance of your module with the activity as an argument. The dependency will then correctly be supplied.