我试图把头放在Dagger 2的范围内,特别是范围图的生命周期。如何创建离开示波器时将要清理的组件。
对于Android应用程序,通常使用Dagger 1.x在应用程序级别具有根作用域,并将其扩展以在活动级别创建子作用域。
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中可确保范围图可以自由进行垃圾收集。
编辑
杰西·威尔逊(JesseWilson)最近发布了一个小窍门
Dagger 1.0严重破坏了其作用域名称… @Singleton批注同时用于根图和自定义图,因此要弄清楚事物的实际作用域是非常棘手的。
我已阅读/听到的所有其他内容都指向Dagger 2,以改善示波器的工作方式,但我仍在努力了解两者之间的区别。根据下面的@Kirill
Boyarshinov的评论,与往常一样,组件或依赖项的生命周期仍由具体引用来确定。那么Dagger 1.x和2.0范围之间的区别纯粹是语义上的清楚吗?
依赖关系是否@Singleton
存在。根图和子图中的依赖项也同样如此,从而导致该依赖关系绑定到哪个图上的模棱两可(请参阅Dagger中子图内的Singleton被缓存,或者在创建新的活动子图时将始终重新创建它们)是建造的?
自定义范围允许您创建在语义上清晰的范围,但在功能上等同于@Singleton
在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唯一的保证是,对于给定的html" target="_blank">组件,带范围注释的方法将返回单个实例。我还假设Dagger
2在组件上使用了范围注释,以验证模块仅提供了相同范围内或非范围内的依赖项。
依赖关系仍然是单例或非单例,但@Singleton
现在适用于应用程序级单例实例,而自定义范围是注释具有较短生命周期的单例依赖项的首选方法。
开发人员负责通过删除不再需要的引用来管理组件/依赖项的生命周期,并负责确保组件仅在其预期的作用域中创建一次,但是自定义作用域注释使识别该作用域更加容易。
我对Dagger 2范围和生命周期的理解正确吗?
*实际上不是$ 64‘000的问题。
至于你的问题
是什么决定了Dagger 2中组件(对象图)的生命周期?
简短的答案是 您确定 。可以给您的组件一个范围,例如
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationScope {
}
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
这些对于您有两点有用:
。
@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();
}
}
这可以通过@Subcomponent
注释或组件依赖性来完成。我个人更喜欢依赖项。
@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
来访问其自己的范围内依赖项的原因。
一个组件只能对一个范围内的组件进行子范围划分。不允许多个作用域组件依赖。
Jesse Wilson最近发表了一篇《罪责声明》 Dagger 1.0把它的作用域名称搞得一团糟...@singleton注释同时用于根图和自定义图,所以弄清楚一个东西的实际作用域是什么很棘手。 其他我读到/听到的都指向Dagger 2改进了作用域的工作方式,但我很难理解两者之间的区别。根据@Kirill Boyarshinov在下面的评论,一个组件或依赖项的生命周期仍然是由具体的引用来确定的。
我需要从当前feature文件调用一个.feature文件,并将一个变量从被调用的.feature文件传递给调用方.feature文件。我使用了karate.set()和karate.get(),但变量似乎不是这样传递的。在调用的.feature文件中,我将变量设置为“*def token=karate.get('xenpauth')”。在调用的.feature文件中,我尝试获得类似“*defxe
我对Spring的生命周期感到困惑。 上面的代码片段是否创建了对象? 如果上述答案为真。 a) 然后,对于作用域为“singleton”的bean,获取在上述代码片段中创建的对象。我是对还是错? b)对于范围为“原型”的情况,创建的对象是否未使用。因为,容器总是返回新对象。 上面的代码片段是否创建了对象? 如果答案是假的, Spring框架如何验证bean定义是否正确。 根据亨利的回答 通常,单例
一般来说,一个组件类由 extends Component 创建,并且提供一个 render 方法以及其他可选的生命周期函数、组件相关的事件或方法来定义。 {% include './share/simple-component.md' %} getInitialState 初始化 this.state 的值,只在组件装载之前调用一次。 如果是使用 ES6 的语法,你也可以在构造函数中初始化状态,
每个响应对象只有当在 servlet 的 service 方法的范围内或在 filter 的 doFilter 方法范围内是有效的,除非该组件关联的请求对象已经开启异步处理。如果相关的请求已经启动异步处理,那么直到AsyncContext 的 complete 方法被调用,请求对象一直有效。为了避免响应对象创建的性能开销,容器通常回收响应对象。在相关的请求的startAsync 还没有调用时,开发
每个请求对象只在一个 servlet 的 service 方法的作用域内,或过滤器的 doFilter 方法的作用域内有效,除非该组件启用了异步处理并且调用了请求对象的 startAsync 方法。在发生异步处理的情况下,请求对象一直有效,直到调用 AsyncContext 的 complete 方法。容器通常会重复利用请求对象,以避免创建请求对象而产生的性能开销。开发人员必须注意的是,不建议在上