android - dagger-android 自定义作用域

标签 android dagger-2 dagger

我对使用 dagger-android 的 Dagger 中的作用域依赖感到困惑。

使用 @ContributesAndroidInjetor 我有一个类似下面的代码:

@Module
public abstract class ActivityBindingModule {

    @ContributesAndroidInjector(modules = PotatoesModule.class)
    public abstract MainActivity contributeMainActivityInjector();

    @ContributesAndroidInjector
    public abstract UserActivity contributeUserActivity();
}

ActivityBindingModule 在我的 AppComponent 中被定义为一个模块。但问题是。我怎样才能做类似的事情

@UserScope
@Component(dependencies = AppComponent.class)
public interface UserComponent {...}

并注释一个 Activity 以使用该范围?我所有的依赖项都在 Activity “本地单例”中吗?因为每个 Activity 注入(inject)器都是 AppComponent 的子组件。

也许我不理解使用 dagger-android 的“作用域”的概念,如果有人能解释一下,我会很高兴。

最佳答案

这里有一些关于作用域的说明:

假设您有一个 AppComponent 并使用 @Singleton 注释对其进行注释:

@Singleton
@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class

})
public interface AppComponent extends AndroidInjector<BaseApplication> {

    @Component.Builder
    interface Builder{

        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }

}

并且您有一个 AppModule,它提供应用程序级别的依赖项(例如,您使用 @Singleton 注释的 Retrofit 实例):

@Module
public class AppModule {

    @Singleton
    @Provides
    static Retrofit provideRetrofitInstance(){
        return new Retrofit.Builder()
                .baseUrl(Constants.BASE_URL)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
}

然后我们可以说 AppComponent 拥有 @Singleton 范围,因此您提供的 Retrofit 实例上的 @Singleton 注释现在具有与 AppComponent 相同的范围 - 即它是应用程序级范围。

如果你想将范围限定为 Activity - 你应该像这样创建一个自定义范围:

@Scope
@Documented
@Retention(RUNTIME)
public @interface UserScope {
}

然后在您的 ActivityBindingModule(您编写的)中,如果您希望 UserActivity“拥有”@UserScope 范围,请使用 @UserScope 注释 UserActivity。此外,在 @ContributesAndroidInjector 旁边添加一个模块 - 我们称它为 UserModule.class:

@Module
public abstract class ActivityBindingModule {

    @ContributesAndroidInjector(modules = PotatoesModule.class)
    public abstract MainActivity contributeMainActivityInjector();

    @UserScope
    @ContributesAndroidInjector(modules = UserModule.class)
    public abstract UserActivity contributeUserActivity();
}

现在,创建 UserModule.class 并使用 @UserScope 注释提供的依赖项:

@Module
public class UserModule {

    @UserScope
    @Provides
    static User provideUser(){
        return new User();
    }
}

此依赖项现在与 UserActivity 具有相同的范围。因此,当 UserActivity 被销毁并重新创建时,所提供的依赖项也将被销毁并重新创建。

结束语:

创建一个 POJO 用户:

public class User {
    public User() {

    }
}

现在,如果您转到 UserActivity 并执行以下操作:

public class UserActivity extends DaggerAppCompatActivity {

 private static final String TAG = "UserActivity";

 @Inject
 User aUser;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user);

        Log.d(TAG, "onCreate: " + aUser);

    }
}

如果您现在运行您的应用程序,您将看到一个内存地址被打印到日志中。旋转设备以销毁并重新创建 Activity ,您将看到内存地址发生变化。这就是我们知道@UserScope 工作正常的方式。

如果你想看到你的应用程序作用域,即@Singleton,那么创建一个 AppModule,将它添加到你的 AppComponent 中,并在该模块中提供一个 User 依赖项,并用 @Singleton 注释它。请记住也要使用 @Named 注释,因为您现在有 2 个依赖项,它们具有相同的返回类型(都可以在 Activity 范围内访问)。

再次转到您的 UserActivity 并注入(inject)两个用户(记得使用@Named)。将其记录在另一个日志语句中,在旋转设备后,您会注意到应用程序范围的依赖项具有相同的内存地址。

我希望这一切都解决了。

关于android - dagger-android 自定义作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47804043/

相关文章:

android - 将 3gp 文件分享到 youtube 和 facebook

android - Dagger 生成多个改造拦截器实例

java - Dagger 2.0 - AppEngine - gradle 配置

android - TextInputLayout 监听器不工作

android - Android Studio生成签名的APK

android - Dagger 2 : What does @Module(includes =) do?

android - 在 Dagger 2.15 中,我是否需要在每个 Activity 上添加注入(inject)行?

java - Dagger 2 问题覆盖单个提供来自应用程序使用的库中模块的注释方法

gradle - Espresso + RoboBinding + Dagger : Dependency management with gradle

android - AlertDialog AppCompat 宽度和高度