Android上的Dagger 2:在Activity和保留的Fragment中注入相同的依赖项 [英] Dagger 2 on Android: inject same dependency in Activity and retained Fragment

查看:226
本文介绍了Android上的Dagger 2:在Activity和保留的Fragment中注入相同的依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有要插入保留的Fragment中的类 F1 F2 的对象。我还有一个依赖于Activity的 A 类对象,我希望将其注入到该Activity和附加到该Activity的Fragment Manager中的保留Fragment中。我写下面的代码。首先,用于Activity依赖项的模块:

I have objects of classes F1 and F2 that I want to inject in a retained Fragment. I also have an object of class A that depends on Activity, and I want it to be injected in that Activity and in a retained Fragment attached to that Activity's Fragment Manager. I write the following code. First, the module for the Activity dependency:

@Module
public class MainActivityModule {
    private Activity mActivity;

    public MainActivityModule(Activity activity) {
        mActivity = activity;
    }

    @Provides
    @ActivityScope
    public A provideA() {
        return new A(mActivity);
    }
}

然后,对应的组件必须使 A 对象可用于其依赖组件:

Then, the corresponding component, that must make the A object available to its dependent components:

@ActivityScope
@Component(modules = {MainActivityModule.class})
public interface MainActivityComponent {
    void inject(MainActivity activity);

    // make the A object available to dependent components
    A getA();
}

我还编写了与片段相关的模块:

I also write the Fragment-related module:

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

最后,我注入对 A的依赖项中的Activity,我还需要在其上调用特定的生命周期方法。活动还提供了一种获取组件的方法,以便Fragment在构建自己的组件时可以使用它:

Finally, I inject the dependency on A in the Activity, where I also need to call specific life cycle methods on it. The Activity also provides a method to get the component so that the Fragment is able to use it when building its own component:

// in MainActivity.onCreate
mActivityComponent = DaggerMainActivityComponent.builder()
        .mainActivityModule(new MainActivityModule(this))
        .build();
mActivityComponent.inject(this);
mA.onCreate();

,我尝试注入对 A ,片段中的 F1 F2

and I try to inject the dependencies on A, F1, F2 in the Fragment, too:

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

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

However, since the Fragment is retained, when the Activity is destroyed and recreated by the system reacting to a configuration change (e.g. a device rotation), the Fragment maintains a reference to the old A instance, while the new Activity has correctly recreated a new A instance to go with it. To work around this problem, I have to create the FragmentComponent and inject dependencies in MyFragment.onActivityCreated rather than MyFragment.onCreate. On the other hand, this implies that F1 and F2 dependencies are recreated every time the activity is destroyed and recreated; but they are Fragment-scoped dependencies, so they should follow the Fragment life cycle instead of the Activity's.

因此,我的问题是:是否可以有不同的选择范围内的依赖项注入到保留的Fragment中?理想情况下,应将 F1 F2 依赖项注入 MyFragment.onCreate ,而 A 依赖项应注入 MyFragment.onActivityCreated 中。我尝试使用两个不同的组件,但是似乎无法执行部分注入。目前,我最终在 MyFragment.onActivityCreated 中添加了对片段 A 依赖项的显式重新分配,但这并不是真正的注入, 你懂。可以用更好的方法吗?

Therefore, my question is as follows: is it possible to have differently-scoped dependencies injected in a retained Fragment? Ideally, F1 and F2 dependencies should be injected in MyFragment.onCreate, while A dependency should be injected in MyFragment.onActivityCreated. I tried using two different components, but it seems not to be possible to perform partial injection. Currently, I ended up adding an explicit reassignment of the Fragment A dependency in MyFragment.onActivityCreated, but that's not really injection, you know. Could this be done in a better way?

推荐答案

考虑到您保留的碎片寿命比您的活动更长,我敢打赌正确的方法是使 FragmentScope 包含 ActivityScope ,而不是相反。

Considering your retained fragment lives longer than your activity, I'd wager that the proper way to do this would be to make the FragmentScope contain the ActivityScope, and not vice versa.

表示您的FragmentComponent

Meaning your FragmentComponent would have

@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模块作为依赖项。

Which is possible if your Fragment injected classes don't rely on the Activity module as dependencies.

这可以通过类似于

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

这篇关于Android上的Dagger 2:在Activity和保留的Fragment中注入相同的依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆