我对使用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注入器都是AppComponent的子组件。
也许我不理解使用dagger-android的“范围”的概念,如果有人能够解释它,我会很高兴。
答案 0 :(得分:1)
以下是有关范围的说明:
假设您有一个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进行注释的改造实例):
@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具有相同的范围-即它是应用程序级范围。
如果您希望将范围限定为“活动”,则应进行如下自定义范围:
@Scope
@Documented
@Retention(RUNTIME)
public @interface UserScope {
}
然后,如果要让UserActivity拥有@UserScope范围,则在您编写的ActivityBindingModule中,用@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);
}
}
如果您现在运行应用程序,您将看到一个内存地址被打印到日志中。旋转设备以销毁并重新创建活动,您将看到内存地址已更改。这就是我们知道@UserScope正常工作的方式。
如果要查看应用程序作用域(即@Singleton),然后创建一个AppModule,将其添加到AppComponent并在该模块中提供User依赖项,并使用@Singleton对其进行注释。请记住,也要使用@Named批注,因为您现在有2个依赖项,它们具有相同的返回类型(都可以在Activity Scope中访问)。
再次转到您的UserActivity并注入两个用户(请记住使用@Named)。将其记录在另一个日志记录语句中,旋转设备后,您会发现您具有与Application作用域相关的相同的内存地址。
我希望这可以解决问题。
答案 1 :(得分:0)
我的所有依赖项都在“本地单身人士”活动中吗?因为每个Activity注入器都是AppComponent的子组件。
dagger-android生成的子组件是无范围的,除非您使用范围注释@ContributesAndroidInjector
- 带注释的方法。
但问题是。如何执行
... @Component(dependencies = AppComponent.class) ...
之类的操作并注释活动以使用该范围?
据我所知,你只能使用带有dagger-android的子组件。此外,活动子组件必须在安装在应用程序组件中的模块中声明,而片段子组件可以在安装在应用程序,活动或片段组件中的模块中声明。
我不确定你的意思是“注释一个活动来使用那个范围”。