Android Dagger-2 how to provide the dependency for method parameters

江枫思渺然 提交于 2019-12-04 06:28:51

问题


I have a module FragmentModule

@Module
public class FragmentModule
{
    @Provides
    public static PickerDashboardFragment providesPickerDashboard(int status, String name, Object someComplexObject)
    {
        PickerDashboardFragment fragment = new PickerDashboardFragment();
        Bundle b = new Bundle();
        b.putInt("status", status);
        b.putString("name", name);
        b.putInt("object", someComplexObject);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Provides
    public static PickingFragment providesPickingFragment()
    {
        PickingFragment fragment = new PickingFragment();
        return fragment;
    }
}

Here's my Component class

@Component(modules = {UtilModule.class, FragmentModule.class})
public interface ApplicationComponent
{
    void inject(PickerDashboardActivity target);
}

In my activity this is how i'm injecting the PickerDashboardActivity

@Inject 
PickerDashboardFragment frag;

ApplicationComponent component = DaggerApplicationComponent.builder().build();
        component.inject(this);

My question is what's the best and easiest way to provide the dependencies for PickerDashboardFragment providesPickerDashboard(int status, String name, Object someComplexObject) i.e status, name and someComplexObject.

Best Regards


回答1:


Add attributes and Provides methods to your module like this:

@Module
public class FragmentModule
{

    private final int status;
    private final String name;
    private final Object someComplexObject;

    public FragmentModule(int status, String name, Object someComplexObject) {
        this.status = status;
        this.name = name;
        this.someComplexObject = someComplexObject;
    }

    @Provides
    int providesStatus() {
        return status;
    }

    @Provides
    String providesName() {
        return name;
    }

    @Provides
    Object providesSomeComplexObject() {
        return someComplexObjext;
    }

    @Provides
    public static PickerDashboardFragment providesPickerDashboard(int status, String name, Object someComplexObject)
    {
        PickerDashboardFragment fragment = new PickerDashboardFragment();
        Bundle b = new Bundle();
        b.putInt("status", status);
        b.putString("name", name);
        b.putInt("object", someComplexObject);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Provides
    public static PickingFragment providesPickingFragment()
    {
        PickingFragment fragment = new PickingFragment();
        return fragment;
    }
}

Having a module providing ints and Strings will probably make you use some qualifiers (such as Named) in order to avoid collisions




回答2:


Don't inject Fragments into your Activities using Dagger 2. Why? Fragments have a lifecycle controlled by the Android OS. When you add a Fragment to an Activity using a transaction, the FragmentManager will retain a reference to the Fragment. When the Activity instanceState is saved, the Fragments added to FragmentManager will be saved. When the Activity is restored, if you request injection without checking for the presence of the Fragment in the FragmentManager, your Activity begin to reference two instances of the Fragment and create a memory leak.

For this reason, in void onCreate(Bundle savedInstanceState) method you should check for the presence of the retained Fragment in the FragmentManager rather than request injection from Dagger 2. If the Fragment is not retained then you can instantiate it at that point. It is perfectly fine to use the new keyword or static factories for this.

Example:

MyFragment frag;

void onCreate(Bundle savedInstanceState) {
     setContentView(R.layout.content);
     frag = fragmentManager.findFragmentByTag(MyFragment.TAG);
     if (frag == null) {
         frag = MyFragment.instantiate(new Bundle());
     }
}

However, at another level it seems you are asking how to combine parameters and dependencies. A good solution for these is often Factories. Say you have a CoffeeMaker:

class CoffeeMaker {

    private final Kettle kettle;
    private final Grinder grinder;
    private final BeanFlavour beanFlavour;

    CoffeeMaker(Kettle kettle, Grinder grinder, BeanFlavour beanFlavour) {
        this.kettle = kettle;
        this.grinder = grinder;
        this.beanFlavour = beanFlavour;
    }
}

The beanFlavour is variable (dark, roasted etc.) and varies and so is more like a parameter than a dependency. You could then write a CoffeeMakerFactory and inject this using Dagger 2:

 class CoffeeMakerFactory {

     private final Kettle kettle;
     private final Grinder grinder;

     @Inject
     CoffeeMakerFactory(Kettle kettle, Grinder grinder) {
         this.kettle = kettle;
         this.grinder = grinder;
     }

     public CoffeeMaker create(BeanFlavour beanFlavour) {
         return new CoffeeMaker(kettle, grinder, beanFlavour);
     }
 }

Factories are the standard solution for a combination of dependency and parameters see here and they can even be be generated using code generation tools like Google Auto.



来源:https://stackoverflow.com/questions/45011596/android-dagger-2-how-to-provide-the-dependency-for-method-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!