Dagger-Android自定义作用域

9

I'm confused about scoped dependencies in Dagger using dagger-android.

Using @ContributesAndroidInjetor I have a code something like the following:

@Module
public abstract class ActivityBindingModule {

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

    @ContributesAndroidInjector
    public abstract UserActivity contributeUserActivity();
}

The ActivityBindingModule is defined as a module in my AppComponent. But the problem is. How can I do something like

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

And annotate an Activity to use that scope? Is all my dependencies inside activity "local singletons"? Because each Activity injector is a subcomponent of AppComponent.

Maybe I'm not understanding the concept of "scopes" using dagger-android, I would be glad if someone could explain it.

2个回答

3

这里是关于作用域的澄清:

假设你有一个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 User:

public class User {
    public User() {

    }
}

现在,如果您进入“用户活动”并执行以下操作:

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);

    }
}

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

如果您想要查看应用程序作用域(即@Singleton)的实际操作,请创建一个AppModule,将其添加到AppComponent中,并在该模块中提供一个用户依赖项,并用@Singleton进行注释。记得也要使用@Named注解,因为您现在有两个提供相同返回类型的依赖项(可以在活动范围内访问它们)。

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

希望这能澄清问题。


0
所有我的依赖都在Activity的“本地单例”中吗?因为每个Activity注入器都是AppComponent的子组件。 dagger-android生成的子组件没有作用域,除非您使用@ContributesAndroidInjector注释方法并添加作用域。 但问题是。我该如何做类似... @Component(dependencies = AppComponent.class) ... 并注释一个Activity以使用该作用域? 据我所知,您只能使用dagger-android的子组件。此外,活动子组件必须在安装在应用程序组件中的模块中声明,而片段子组件可以在安装在应用程序、活动或片段组件中的模块中声明。 不过,“注释一个Activity以使用该作用域”这句话不是很明白。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接