Android上的Dagger 2:在Activity中注入相同的依赖项并保留Fragment

我有类F1F2对象,我想在保留的片段中注入。 我还有一个依赖于Activity的A类对象,我希望它被注入到该Activity中,并且附加到该Activity的Fragment Manager中的保留Fragment中。 我写下面的代码。 首先,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(); 

我也尝试在片段中注入AF1F2上的依赖项:

 // in MyFragment.onCreate FragmentComponent component = DaggerFragmentComponent.builder() .fragmentModule(new FragmentModule()) .mainActivityComponent(((MainActivity) getActivity()).getComponent()) .build(); component.inject(this); 

但是,由于保留了Fragment,当系统销毁并重新创建Activity以响应配置更改(例如设备轮换)时,Fragment维护对旧A实例的引用,而新Activity正确地重新创建了一个A与之相关A实例。 要解决这个问题,我必须创建FragmentComponent并在MyFragment.onActivityCreated而不是MyFragment.onCreate注入依赖MyFragment.onCreate 。 另一方面,这意味着每次销毁和重新创建活动时都会重新创建F1F2依赖项; 但它们是片段范围的依赖项,因此它们应该遵循Fragment生命周期而不是Activity的。

因此,我的问题如下:是否可以在保留的片段中注入不同范围的依赖项? 理想情况下,应在MyFragment.onCreate注入F1F2依赖MyFragment.onCreate ,而应在MyFragment.onActivityCreated注入依赖MyFragment.onActivityCreated 。 我尝试使用两种不同的组件,但似乎无法进行部分注射。 目前,我最终在MyFragment.onActivityCreated添加了片段A依赖项的显式重新分配,但是这不是真正的注入,你知道。 这可以用更好的方式完成吗?

Related of "Android上的Dagger 2:在Activity中注入相同的依赖项并保留Fragment"

考虑到你保留的碎片寿命比你的活动长,我敢打赌,正确的方法是让FragmentScope包含ActivityScope ,反之亦然。

意味着你的FragmentComponent会有

 @FragmentScope @Component(modules = {FragmentModule.class}) public interface FragmentComponent { void inject(MyFragment presenter); } 

你的Activity组件会有

 @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(); } }