【问题标题】:dagger-android custom scopesdagger-android 自定义范围
【发布时间】:2017-12-14 00:14:01
【问题描述】:

我对使用 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 的“范围”的概念,如果有人能解释一下,我会很高兴。

【问题讨论】:

    标签: android dagger-2 dagger


    【解决方案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 {
    }
    

    然后在您的 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);
    
        }
    }
    

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

    如果您想查看您的应用程序范围,即@Singleton,则创建一个 AppModule,将其添加到您的 AppComponent 并在该模块中提供用户依赖项并使用 @Singleton 对其进行注释。请记住也要使用 @Named 注释,因为您现在有 2 个依赖项提供了相同的返回类型(都可以在 Activity 范围内访问)。

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

    我希望这可以解决问题。

    【讨论】:

      【解决方案2】:

      活动中的所有依赖项都是“本地单例”吗?因为每个Activity注入器都是AppComponent的一个子组件。

      dagger-android 生成的子组件是无作用域的,除非你用作用域注释@ContributesAndroidInjector-annotated 方法。

      但问题是。我怎样才能做类似... @Component(dependencies = AppComponent.class) ... 的事情并注释一个活动以使用该范围?

      据我所知,你只能使用带有 dagger-android 的子组件。此外,活动子组件必须在应用程序组件中安装的模块中声明,而片段子组件可以在应用程序、活动或片段组件中安装的模块中声明。

      不过,我不确定您所说的“注释 Activity 以使用该范围”是什么意思。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-10
        • 1970-01-01
        • 1970-01-01
        • 2015-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多