dagger-android自定义范围

时间:2017-12-14 00:14:02

标签: 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注入器都是AppComponent的子组件。

也许我不理解使用dagger-android的“范围”的概念,如果有人能够解释它,我会很高兴。

2 个答案:

答案 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的子组件。此外,活动子组件必须在安装在应用程序组件中的模块中声明,而片段子组件可以在安装在应用程序,活动或片段组件中的模块中声明。

我不确定你的意思是“注释一个活动来使用那个范围”。