我有自定义范围:
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity { }
和使用此注释的组件:
@PerActivity
@Component(modules = {ActivityModule.class}, dependencies = AppComponent.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
和提供MainPresenter依赖关系的模块:
@Module
public class ActivityModule {
@PerActivity
@Provides
public MainPresenter provideMainPresenter(){
return new MainPresenter();
}
}
这是MainPresenter注入的MainActivity:
public class MainActivity extends AppCompatActivity implements MainView {
@PerActivity
@Inject
MainPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.appComponent(DaggerAppComponent.builder().build())
.build()
.inject(this);
}
}
我的问题:在配置更改(方向更改)后重新创建演示者。
我的问题:如何让它只为一项活动创建一次?
答案 0 :(得分:5)
Dagger创建的Java代码没有任何魔力。这是一些可以做一些事情的类,但它们不会读/写全局状态或有其他副作用。如果创建组件,则创建它包含的所有对象。由一个组件提供的@PerActivity
范围对象永远不会与从同一范围的另一个组件提供的对象相同。
MyComponent.create().getPresenter() == MyComponent.create().getPresenter() // always false (with same scope)
这就是说,你的代码示例中有一个主要问题,即你有一个AppComponent
,但你不断重新创建它,很可能而不是你想要的或者应该这样做。这将为每个活动重新创建@Singleton
。
DaggerActivityComponent.builder()
.appComponent(DaggerAppComponent.builder().build()) // DON'T !!
.build()
.inject(this);
您需要在Application
类中缓存此组件并检索它,例如像((MyApp) getApplication).getComponent()
这样的东西。否则,您的@Singleton
类都不会被重用。
所有这些说明,当您在@PerActivity
方法中创建新的ActivityComponent(DaggerActivityComponent.build()
)时,作用域onCreate
的演示者将始终是新对象。您重新创建组件,该新组件将创建新对象。这是预期的行为,因为否则会出现内存泄漏和其他意外的副作用。 (想象一下,演示者保留了对活动的引用!内存将泄漏,UI更新将崩溃或被忽略。)
要重复使用同一个演示者,您必须将演示者移动到范围内。您可以将演示者设为@Singleton
并将其保存在AppComponent
中,也可以尝试在中间添加另一层组件(AppComponent -> ActivityCacheComponent -> ActivityComponent
),但大多数我见过的项目不会添加这个中间层,因为它增加了很多复杂性。你要么拥有保存数据的单身,而且应该是长寿的,或者你有便宜的创作者,可以与活动一起轻松地重新创建。