我想要在保留的片段中注入类F1
和F2
的对象。我还有一个依赖于Activity的类A
的对象,我希望它被注入到该Activity中以及附加到该Activity的片段管理器的保留片段中。我写下面的代码。首先,Activity依赖的模块:
@Module
public class MainActivityModule {
private Activity mActivity;
public MainActivityModule(Activity activity) {
mActivity = activity;
}
@Provides
@ActivityScope
public A provideA() {
return new A(mActivity);
}
}
然后,相应的组件必须使A
对象可用于其依赖组件:
@ActivityScope
@Component(modules = {MainActivityModule.class})
public interface MainActivityComponent {
void inject(MainActivity activity);
// make the A object available to dependent components
A getA();
}
我还写了与Fragment相关的模块:
@Module
public class FragmentModule {
@Provides
@FragmentScope
public F1 provideF1() {
return new F1();
}
@Provides
@FragmentScope
public F2 provideF2() {
return new F2();
}
}
及其相应的组成部分:
@FragmentScope
@Component(modules = {FragmentModule.class}, dependencies = {MainActivityComponent.class})
public interface FragmentComponent {
void inject(MyFragment presenter);
}
最后,我在Activity中注入了对A
的依赖,我还需要在其上调用特定的生命周期方法。 Activity还提供了一种获取组件的方法,以便Fragment能够在构建自己的组件时使用它:
// in MainActivity.onCreate
mActivityComponent = DaggerMainActivityComponent.builder()
.mainActivityModule(new MainActivityModule(this))
.build();
mActivityComponent.inject(this);
mA.onCreate();
我尝试在片段中的A
,F1
,F2
上注入依赖项:
// in MyFragment.onCreate
FragmentComponent component = DaggerFragmentComponent.builder()
.fragmentModule(new FragmentModule())
.mainActivityComponent(((MainActivity) getActivity()).getComponent())
.build();
component.inject(this);
但是,由于保留了Fragment,当系统销毁并重新创建Activity以响应配置更改(例如设备轮换)时,Fragment会维护对旧A
实例的引用,而new Activity已正确地重新创建了一个新的A
实例。要解决此问题,我必须在FragmentComponent
而不是MyFragment.onActivityCreated
中创建MyFragment.onCreate
并注入依赖项。另一方面,这意味着每次销毁和重新创建活动时都会重新创建F1
和F2
个依赖关系;但它们是Fragment-scoped依赖项,因此它们应该遵循Fragment生命周期而不是Activity。
因此,我的问题如下:是否可以在保留的片段中注入不同范围的依赖项?理想情况下,F1
和F2
依赖项应注入MyFragment.onCreate
,而A
依赖项应注入MyFragment.onActivityCreated
。我尝试使用两种不同的组件,但似乎无法执行部分注入。目前,我最终在A
中添加了片段MyFragment.onActivityCreated
依赖关系的明确重新分配,但是这并不是真正的注入,你知道。这可以用更好的方式完成吗?
答案 0 :(得分:8)
考虑到您保留的片段的续航时间比您的活动长,我谨慎地说明,执行此操作的正确方法是使FragmentScope
包含ActivityScope
,反之亦然。< / p>
表示你的FragmentComponent会有
@FragmentScope
@Component(modules = {FragmentModule.class})
public interface FragmentComponent {
void inject(MyFragment presenter);
}
您的活动组件将
@ActivityScope
@Component(dependencies = {FragmentComponent.class}, modules = {MainActivityModule.class})
public interface MainActivityComponent extends FragmentComponent { //provision methods
void inject(MainActivity activity);
// make the A object available to dependent components
A getA();
}
如果您的Fragment
注入的类不依赖于Activity模块作为依赖项,那么这是可能的。
这可以用类似于
的东西来完成public class MainActivity extends AppCompatActivity {
private MainActivityComponent mainActivityComponent;
private MyFragment myFragment;
@Override
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
if(saveInstanceState == null) { // first run
myFragment = new MyFragment(); //headless retained fragment
getSupportFragmentManager()
.beginTransaction()
.add(myFragment, MyFragment.class.getName()) //TAG
.commit();
} else {
myFragment = (MyFragment)(getSupportFragmentManager()
.findFragmentByTag(MyFragment.class.getName()));
}
}
@Override
public void onPostCreate() {
mainActivityComponent = DaggerMainActivityComponent.builder()
.fragmentComponent(myFragment.getComponent())
.build();
}
}
和
public class MyFragment extends Fragment {
public MyFragment() {
this.setRetainInstance(true);
}
private FragmentComponent fragmentComponent;
@Override
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
this.fragmentComponent = DaggerFragmentComponent.create();
}
public FragmentComponent getFragmentComponent() {
return fragmentComponent;
}
}
编辑:
public class MyFragment extends Fragment {
public MyFragment() {
this.setRetainInstance(true);
this.fragmentComponent = DaggerFragmentComponent.create();
}
private FragmentComponent fragmentComponent;
public FragmentComponent getFragmentComponent() {
return fragmentComponent;
}
}
public class MainActivity extends AppCompatActivity {
private MainActivityComponent mainActivityComponent;
private MyFragment myFragment;
@Inject
A mA;
@Override
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
if(saveInstanceState == null) { // first run
myFragment = new MyFragment(); //headless retained fragment
getSupportFragmentManager()
.beginTransaction()
.add(myFragment, MyFragment.class.getName()) //TAG
.commit();
} else {
myFragment = (MyFragment)(getSupportFragmentManager().findFragmentByTag(MyFragment.class.getName()));
}
mainActivityComponent = DaggerMainActivityComponent.builder()
.fragmentComponent(myFragment.getComponent())
.build();
mainActivityComponent.inject(this);
mA.onCreate();
}
}