Dagger2定制范围:如何自定义范围(@ActivityScope)实际工作?范围、自定义、实际、工作

2023-09-12 05:04:11 作者:♂ 光着脚丫逃跑-°

我读源$ C ​​$下 Dagger2组件作用域测试在GitHub上,我已经在其他项目中,包括4模块出现了自定义范围名为 @ActivityScope 活动的定义,但我已经看到了它的 CleanArchitecture ,有它 @PerActivity 范围

I am reading the source code for Dagger2 Component Scopes Test on GitHub, and I've seen a "custom scope" defined for activities called @ActivityScope, but I've seen it in other projects including the 4-module CleanArchitecture that has its @PerActivity scope.

不过,从字面上看,在code为 @ActivityScope 标注如下:

But literally, the code for the @ActivityScope annotation is the following:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.inject.Scope;

/**
 * Created by joesteele on 2/15/15.
 */
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}

和它是神奇可用的模块:

And it is "magically" usable in Modules:

@Module
public class ActivityModule {
  @Provides @ActivityScope Picasso providePicasso(ComponentTest app, OkHttpClient client) {
    return new Picasso.Builder(app)
        .downloader(new OkHttpDownloader(client))
        .listener(new Picasso.Listener() {
          @Override public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) {
            Log.e("Picasso", "Failed to load image: " + uri.toString(), e);
          }
        })
        .build();
  }
}

或 CleanArchitecture 的例子:

@Scope
@Retention(RUNTIME)
public @interface PerActivity {}

@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
  //Exposed to sub-graphs.
  Activity activity();
}

@Module
public class ActivityModule {
  private final Activity activity;

  public ActivityModule(Activity activity) {
    this.activity = activity;
  }

  /**
  * Expose the activity to dependents in the graph.
  */
  @Provides @PerActivity Activity activity() {
    return this.activity;
  }
}

我可以清楚地看到,这必须与JSR-330定制范围,但我的真的不明白究竟是怎么回事,以让这个本code使定模块和/或由给定模块提供给依赖于实际活性的生命周期,什么和那里只存在一个单一的实例,但是只有在该给定的活动活跃

I can clearly see that this has to do with JSR-330 custom scopes, but I really don't understand what exactly is happening here to make it so that this code enables the given module and/or what is provided by a given module to depend on the actual Activity lifecycle, and for there to exist only a single instance but only if that given activity is active.

该文档说的:

Scope

Dagger 1 only supported a single scope: @Singleton. 
Dagger 2 allows users to any well-formed scope annotation. 
The Component docs describe the details of 
    how to properly apply scope to a component.

报告说,看看组件文档页面,但给了我404.我也看到这个,但是...

It says to look at the Component docs page, but that gives me 404. I also saw this, but...

请问在澄清一些帮助,为什么指定这个自定义范围内神奇地使的活动级别范围工作没有问题?

May I ask for some help in clarifying why specifying this custom scope magically makes Activity-level scopes work without an issue?

(答案是,一个子范围可以从超级作用域接受的依赖,以及子范围存在,只要成分一样。而且,你需要指定你的模块的范围,你需要指定组件的依赖于子范围一个超级作用域。)

(The answer is, a subscope can receive dependencies from its superscope, and a subscope exists as long as the component does. And that you need to specify the scopes on your modules, and you need to specify your component dependencies to subscope one superscope.)

推荐答案

值得注意的是,显然Dagger2在每个组件模块创建每个范围提供一个实例。

It is worth noting that apparently Dagger2 creates a single instance per scoped provider in a module per component.

因此​​,为了得到一个范围内的供应商在一个模块中,你需要指定范围的模块供应商的方法。

So in order to get a scoped provider in a module, you need to specify the scope for your module's provider method.

@Module
public class YourModule {
    @Provides
    @YourScope //one per component
    public Something something() { return new SomethingImpl(); }

    @Provides //new instance per injection
    public Otherthing otherthing() { return new OtherthingImpl(); }
}

@Component
@YourScope
public interface YourComponent {
    Something something();
    Otherthing otherthing();

    void inject(YourThing yourThing);
}

之后,是指基里尔的答案;基本上是一个范围本身仅确定它是从其他的一个不同的范围。使用组件的依赖关系(或子组件)创建了一个子范围。

Afterwards, refer to Kirill's answer; essentially a "scope" by itself only determines that it is a different scope from the other one. Using component dependencies (or subcomponents) creates a subscope.

@Module
public class SubModule {
    @Provides
    @SubScope
    public ThatThing thatThing() { return new ThatThingImpl(); }
}

@Component(dependencies={YourComponent.class}, modules={SubModule.class})
@SubScope
public interface SubComponent extends YourComponent {
    ThatThing thatThing();

    void inject(SubThing subThing);
}

一个组件可以依赖于只有一个其他范围的组成部分。

A component can depend on only one other scoped component.