什么决定了Dagger 2中组件(对象图)的生命周期? [英] What determines the lifecycle of a component (object graph) in Dagger 2?

查看:90
本文介绍了什么决定了Dagger 2中组件(对象图)的生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图把头放在Dagger 2中的作用域上,特别是作用域图的生命周期.如何创建一个组件,当离开示波器时将对其进行清理.

I'm trying to wrap my head around scopes in Dagger 2, specifically the lifecycle of scoped graphs. How do you create a component that will be cleaned up when you leave the scope.

在Android应用程序中,通常使用Dagger 1.x在应用程序级别具有根作用域,并将其扩展以在活动级别创建子作用域.

In the case of an Android application, using Dagger 1.x you generally have a root scope at the application level which you'd extend to create a child scope at the activity level.

public class MyActivity {

    private ObjectGraph mGraph;

    public void onCreate() {
        mGraph = ((MyApp) getApplicationContext())
            .getObjectGraph()
            .plus(new ActivityModule())
            .inject(this);
    }

    public void onDestroy() {
        mGraph = null;
    }
}

只要您保留对子作用域的引用,子作用域就一直存在,在这种情况下,子作用域就是您的Activity的生命周期.将引用删除到onDestroy中可确保范围图可以自由进行垃圾收集.

The child scope existed as long as you kept a reference to it, which in this case was the lifecycle of your Activity. Dropping the reference in onDestroy ensured the scoped graph was free to be garbage collected.

编辑

杰西·威尔逊(Jesse Wilson)最近发布了意念

Jesse Wilson recently posted a mea culpa

Dagger 1.0严重破坏了其作用域名称... @Singleton批注用于根图和自定义图,因此要弄清楚事物的实际作用域是很棘手的.

Dagger 1.0 badly screwed up its scope names ... The @Singleton annotation is used for both root graphs and custom graphs, so it's tricky to figure out what the actual scope of a thing is.

以及我已阅读/听到的所有其他内容都指向Dagger 2,以改善示波器的工作方式,但我一直在努力了解两者之间的区别.根据下面的@Kirill Boyarshinov的评论,像往常一样,组件或依赖项的生命周期仍由具体引用来确定.那么Dagger 1.x和2.0范围之间的区别纯粹是出于语义清晰度的问题吗?

and everything else I've read/heard points towards Dagger 2 improving the way scopes work, but I'm struggling to understand the difference. According to @Kirill Boyarshinov's comment below, the lifecycle of a component or dependency is still determined, as usual, by concrete references. So is the difference between Dagger 1.x and 2.0 scopes purely a matter of semantic clarity?

依赖项不是@Singleton.根图和子图中的依存关系也同样如此,导致依存关系绑定到哪个图上的模棱两可(请参阅

Dependencies were either @Singleton or not. This was equally true of dependencies in the root graph and subgraphs, leading to ambiguity as to which graph the dependency was bound to (see In Dagger are Singletons within the sub-graph cached or will they always be recreated when a new activity sub-graph is constructed?)

自定义范围允许您创建语义清晰的范围,但在功能上等同于在Dagger 1.x中应用@Singleton.

Custom scopes allow you to create semantically clear scopes, but are functionally equivalent to applying @Singleton in Dagger 1.x.

// Application level
@Singleton
@Component( modules = MyAppModule.class )
public interface MyAppComponent {
    void inject(Application app);
}

@Module
public class MyAppModule {

    @Singleton @Named("SingletonScope") @Provides
    StringBuilder provideStringBuilderSingletonScope() {
        return new StringBuilder("App");
    }
}


// Our custom scope
@Scope public @interface PerActivity {}


// Activity level
@PerActivty
@Component(
    dependencies = MyAppComponent.class,
    modules = MyActivityModule.class
)
public interface MyActivityComponent {
    void inject(Activity activity);
}

@Module
public class MyActivityModule {

    @PerActivity @Named("ActivityScope") @Provides
    StringBuilder provideStringBuilderActivityScope() {
        return new StringBuilder("Activity");
    }

    @Name("Unscoped") @Provides
    StringBuilder provideStringBuilderUnscoped() {
        return new StringBuilder("Unscoped");
    }
}


// Finally, a sample Activity which gets injected
public class MyActivity {

    private MyActivityComponent component;

    @Inject @Named("AppScope")
    StringBuilder appScope

    @Inject @Named("ActivityScope")
    StringBuilder activityScope1

    @Inject @Named("ActivityScope")
    StringBuilder activityScope2

    @Inject @Named("Unscoped")
    StringBuilder unscoped1

    @Inject @Named("Unscoped")
    StringBuilder unscoped2

    public void onCreate() {
        component = Dagger_MyActivityComponent.builder()
            .myApplicationComponent(App.getComponent())
            .build()
            .inject(this);

        appScope.append(" > Activity")
        appScope.build() // output matches "App (> Activity)+" 

        activityScope1.append("123")
        activityScope1.build() // output: "Activity123"

        activityScope2.append("456")
        activityScope1.build() // output: "Activity123456"

        unscoped1.append("123")
        unscoped1.build() // output: "Unscoped123"

        unscoped2.append("456")
        unscoped2.build() // output: "Unscoped456"

    }

    public void onDestroy() {
        component = null;
    }

}

最重要的是,使用@PerActivity可以传达有关该组件生命周期的意图,但是最终您可以在任何地方/任何时间使用该组件. Dagger唯一的保证是,对于给定的组件,带范围注释的方法将返回单个实例.我还假设Dagger 2在组件上使用了范围注释,以验证模块仅提供了在相同范围内还是在非范围内的依赖项.

The takeaway being that using @PerActivity communicates your intention regarding the lifecycle of this component, but ultimately you can use the component anywhere/anytime. Dagger's only promise is that, for a given component, scope annotated methods will return a single instance. I also assume Dagger 2 uses the scope annotation on the component to verify that modules only provide dependencies that are either in the same scope or non-scoped.

依存关系仍然是单例或非单例,但@Singleton现在用于应用程序级单例实例,自定义作用域是用于注释具有较短生命周期的单例依存关系的首选方法.

Dependencies are still either singleton or non-singleton, but @Singleton is now intended for application-level singleton instances and custom scopes are the preferred method for annotating singleton dependencies with a shorter lifecycle.

开发人员负责通过删除不再需要的引用来管理组件/依赖项的生命周期,并负责确保组件仅在其预期的作用域中创建一次,但是自定义作用域注释使其更易于确定范围.

The developer is responsible for managing the lifecycle of components/dependencies by dropping references that are no longer needed and responsible for ensuring that components are only created once in the scope for which they are intended, but custom scope annotations make it easier to identify that scope.

我对Dagger 2范围和生命周期的理解正确吗?

Is my understanding of Dagger 2 scopes and lifecycles correct?

*实际上不是一个$ 64'000的问题.

推荐答案

关于您的问题

什么决定了Dagger 2中组件(对象图)的生命周期?

What determines the lifecycle of a component (object graph) in Dagger 2?

简短的答案是您确定.可以给您的组件一个范围,例如

The short answer is you determine it. Your components can be given a scope, such as

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationScope {
}

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}

这些对于您有两点有用:

These are useful for you for two things:

  • 范围验证:组件只能具有未限制范围的提供程序,或者具有与您的组件相同范围的范围提供程序.

.

@Component(modules={ApplicationModule.class})
@ApplicationScope
public interface ApplicationComponent {
    Something something();
    AnotherThing anotherThing();

    void inject(Whatever whatever);
}

@Module
public class ApplicationModule {
    @ApplicationScope //application-scoped provider, only one can exist per component
    @Provides
    public Something something() {
         return new Something();
    }

    @Provides //unscoped, each INJECT call creates a new instance
    public AnotherThing anotherThing() {
        return new AnotherThing();
    }
}

  • 允许对范围内的依赖项进行子范围划分,从而允许您创建一个"subscoped"组件,该组件使用"superscoped"组件中提供的实例.
  • 这可以通过@Subcomponent批注或组件依赖项来完成.我个人更喜欢依赖项.

    This can be done with @Subcomponent annotation, or component dependencies. I personally prefer dependencies.

    @Component(modules={ApplicationModule.class})
    @ApplicationScope
    public interface ApplicationComponent {
        Something something();
        AnotherThing anotherThing();
    
        void inject(Whatever whatever);
    
        ActivityComponent newActivityComponent(ActivityModule activityModule); //subcomponent factory method
    }
    
    @Subcomponent(modules={ActivityModule.class})
    @ActivityScope
    public interface ActivityComponent {
        ThirdThingy thirdThingy();
    
        void inject(SomeActivity someActivity);
    }
    
    @Module
    public class ActivityModule {
        private Activity activity;
    
        public ActivityModule(Activity activity) {
            this.activity = activity;
        }
    
        //...
    }
    
    ApplicationComponent applicationComponent = DaggerApplicationComponent.create();
    ActivityComponent activityComponent = applicationComponent.newActivityComponent(new ActivityModule(SomeActivity.this));
    

    或者您可以像这样使用组件依赖项

    Or you can use component dependencies like so

    @Component(modules={ApplicationModule.class})
    @ApplicationScope
    public class ApplicationComponent {
        Something something(); 
        AnotherThing anotherThing();
    
        void inject(Whatever whatever);
    }
    
    @Component(dependencies={ApplicationComponent.class}, modules={ActivityModule.class})
    @ActivityScope
    public interface ActivityComponent extends ApplicationComponent {
        ThirdThingy thirdThingy();
    
        void inject(SomeActivity someActivity);
    }
    
    @Module
    public class ActivityModule {
        private Activity activity;
    
        public ActivityModule(Activity activity) {
            this.activity = activity;
        }
    
        //...
    }
    
    ApplicationComponent applicationComponent = DaggerApplicationComponent.create();
    ActivityComponent activityComponent = DaggerActivityComponent.builder().activityModule(new ActivityModule(SomeActivity.this)).build();
    

    重要事项:

    • 范围提供者为给定范围每个组件创建一个实例.这意味着一个组件会跟踪其自己的实例,但是其他组件没有共享的作用域池或某种魔力.要在给定范围内拥有一个实例,您需要组件的一个实例.这就是为什么必须提供ApplicationComponent来访问其自身的范围内依赖项的原因.

    • A scoped provider creates one instance for that given scope for each component. Meaning a component keeps track of its own instances, but other components don't have a shared scope pool or some magic. To have one instance in a given scope, you need one instance of the component. This is why you must provide the ApplicationComponent to access its own scoped dependencies.

    一个组件只能对一个作用域组件进行子范围划分.不允许多个作用域组件依赖.

    A component can subscope only one scoped component. Multiple scoped component dependencies are not allowed.

    这篇关于什么决定了Dagger 2中组件(对象图)的生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆