当前位置: 首页 > 知识库问答 >
问题:

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

督辉
2023-03-14
public class MyActivity {

    private ObjectGraph mGraph;

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

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

Jesse Wilson最近发表了一篇《罪责声明

Dagger 1.0把它的作用域名称搞得一团糟...@singleton注释同时用于根图和自定义图,所以弄清楚一个东西的实际作用域是什么很棘手。

其他我读到/听到的都指向Dagger 2改进了作用域的工作方式,但我很难理解两者之间的区别。根据@Kirill Boyarshinov在下面的评论,一个组件或依赖项的生命周期仍然是由具体的引用来确定的。那么Dagger1.x和2.0作用域之间的区别纯粹是语义清晰度的问题吗?

// 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唯一的promise是,对于给定的组件,作用域注释的方法将返回单个实例。我还假设Dagger2使用组件上的scope注释来验证模块只提供在相同范围内或不在范围内的依赖项。

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

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

*实际上不是一个$64,000的问题。

共有1个答案

袁耀
2023-03-14

至于你的问题

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

简单的回答是你自己决定。您的组件可以被赋予一个作用域,例如

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

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
    null
@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();
    }
}
    null
@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));

或者您可以使用组件依赖项,如下所示

@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来访问它自己的作用域依赖项的原因。

  •  类似资料:
    • 问题内容: 我试图把头放在Dagger 2的范围内,特别是范围图的生命周期。如何创建离开示波器时将要清理的组件。 对于Android应用程序,通常使用Dagger 1.x在应用程序级别具有根作用域,并将其扩展以在活动级别创建子作用域。 只要您保留对子作用域的引用,该子作用域就一直存在,在这种情况下,这是您的Activity的生命周期。将引用放在onDestroy中可确保范围图可以自由进行垃圾收集。

    • 我需要从当前feature文件调用一个.feature文件,并将一个变量从被调用的.feature文件传递给调用方.feature文件。我使用了karate.set()和karate.get(),但变量似乎不是这样传递的。在调用的.feature文件中,我将变量设置为“*def token=karate.get('xenpauth')”。在调用的.feature文件中,我尝试获得类似“*defxe

    • 我对Spring的生命周期感到困惑。 上面的代码片段是否创建了对象? 如果上述答案为真。 a) 然后,对于作用域为“singleton”的bean,获取在上述代码片段中创建的对象。我是对还是错? b)对于范围为“原型”的情况,创建的对象是否未使用。因为,容器总是返回新对象。 上面的代码片段是否创建了对象? 如果答案是假的, Spring框架如何验证bean定义是否正确。 根据亨利的回答 通常,单例

    • 每个响应对象只有当在 servlet 的 service 方法的范围内或在 filter 的 doFilter 方法范围内是有效的,除非该组件关联的请求对象已经开启异步处理。如果相关的请求已经启动异步处理,那么直到AsyncContext 的 complete 方法被调用,请求对象一直有效。为了避免响应对象创建的性能开销,容器通常回收响应对象。在相关的请求的startAsync 还没有调用时,开发

    • 一般来说,一个组件类由 extends Component 创建,并且提供一个 render 方法以及其他可选的生命周期函数、组件相关的事件或方法来定义。 {% include './share/simple-component.md' %} getInitialState 初始化 this.state 的值,只在组件装载之前调用一次。 如果是使用 ES6 的语法,你也可以在构造函数中初始化状态,

    • 本文向大家介绍本地存储的生命周期是什么?相关面试题,主要包含被问及本地存储的生命周期是什么?时的应答技巧和注意事项,需要的朋友参考一下 : 和 都能控制数据的存储时间。 是一个绝对的过期时间, 是文档被访问之后的存活时间(是相对时间)。默认是 。 : 当会话被关闭后(浏览器、标签页被关闭),就会被清除。与 用法一样。 : 除非被主动清除,不然永久储存在浏览器中。 : 没有过期时间,除非主动清除。