Dagger2 Как @Provide одного типа с двумя разными реализациями

Я очень новичок в Dagger2, только начинаю. Я хочу добиться чего-то подобного, но безуспешно.

Вот мой модуль

@Module
public class UtilModule
{
    @Provides
    @Named("fragmentUtilActivity")
    public FragmentUtils providesFragmentUtilForActivity(Context context)
    {
        return new FragmentUtils(context);
    }

    @Provides
    @Named("fragmentUtilFragment")
    FragmentUtils providesFragmentUtilForFragment(Fragment fragment)
    {
        return new FragmentUtils(fragment);
    }

}

А это мой компонент

@Component(modules = UtilModule.class)
public interface UtilComponent
{
    @Named("fragmentUtilActivity")
    FragmentUtils fragmentUtilsActivity(Context context);

    @Named("fragmentUtilFragment")
    FragmentUtils fragmentUtilsFragment(Fragment fragment);
}

А это мой FragmentUtil класс

package myms.utils;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;

import javax.inject.Inject;

import myms.R;

public class FragmentUtils
{
    private Context context;

    private Fragment hostFragment;

    public FragmentUtils(Context context)
    {
        this.context = context;
    }

    public FragmentUtils(Fragment hostFragment)
    {
        this.hostFragment = hostFragment;
    }

    public void addFragment(Fragment fragment, boolean addToBackStack)
    {
        FragmentTransaction transaction = ((Activity) context).getFragmentManager()
                                                              .beginTransaction();
        transaction.add(R.id.fragment_container, fragment, null);

        if(addToBackStack)
        {
            transaction.addToBackStack(null);
        }

        transaction.commit();
    }

    public void addNestedFragment(Fragment fragment, boolean addToBackStack)
    {
        FragmentTransaction transaction = hostFragment.getChildFragmentManager().beginTransaction();
        transaction.add(R.id.nested_fragment_container, fragment, null);

        if(addToBackStack)
        {
            transaction.addToBackStack(null);
        }

        transaction.commit();
    }

    public void replaceNestedFragment(Fragment fragment, boolean addToBackStack)
    {
        FragmentTransaction transaction = hostFragment.getChildFragmentManager().beginTransaction();
        transaction.replace(R.id.nested_fragment_container, fragment, null);

        if(addToBackStack)
        {
            transaction.addToBackStack(null);
        }

        transaction.commit();
    }
}

Я хочу использовать экземпляр fragmentUtils с двумя разными реализациями: один для активности, а другой для фрагмента. Пожалуйста, помогите мне, что я делаю неправильно.

Также может кто-нибудь помочь мне понять цель void inject (SomeClass) в интерфейсе @Component.

С уважением


person eC Droid    schedule 03.07.2017    source источник
comment
Кто угодно.......?   -  person eC Droid    schedule 03.07.2017
comment
Вы получаете сообщение об ошибке? Пожалуйста, включите описание конкретной проблемы, с которой вы столкнулись.   -  person David Medenjak    schedule 03.07.2017
comment
FragmentUtils похоже, что должно быть 2 разных класса: один работает с фрагментом хоста, а другой работает с активностью. У вас есть 2 набора методов, и вызов неправильного приведет к исключению NullPointerException. Это действительно убедительный признак того, что этот код следует разделить на 2 разных класса.   -  person David Medenjak    schedule 03.07.2017
comment
Спасибо, Дэвид, пожалуйста, просмотрите мой ответ ниже.   -  person eC Droid    schedule 04.07.2017
comment
Итак, вам нужны два независимых экземпляра FragmentUtils? Похоже, что активность и фрагмент, которые их используют, должны иметь свой собственный модуль Dagger. Название UtilModule предполагает, что вы разделяете свои модули по типу того, что они предоставляют. Модули должны быть разделены в зависимости от объема того, что они предоставляют.   -  person Kevin Krumwiede    schedule 04.07.2017
comment
Вы звучите правильно, но это не создаст огромных накладных расходов и большого количества классов для управления. Для простоты я попробовал описанный выше подход. Так что я могу создать класс UtilComponent и соответствующий класс модуля для предоставления зависимостей.   -  person eC Droid    schedule 04.07.2017
comment
Модули должны быть разделены в зависимости от объема того, что они предоставляют. Пожалуйста, предоставьте любую ссылку / документы?   -  person eC Droid    schedule 04.07.2017
comment
@eCDroid Вот руководство по пользовательским областям действия. Если вы избегаете решений из-за огромных накладных расходов и большого количества классов, не пишите приложения для Android. Дамп кучи из стандартного пустого Hello, world! приложение включает в себя более 4000 классов и 700 000 объектов.   -  person Kevin Krumwiede    schedule 19.07.2017


Ответы (1)


Хорошо, после больших усилий я могу решить эту проблему, изменив свой класс UtilMoudle.

package myms.modules;

import android.app.Fragment;
import android.content.Context;

import javax.inject.Named;

import dagger.Module;
import dagger.Provides;
import myms.utils.FragmentUtils;


@Module
public class UtilModule
{
    private Context context;

    private Fragment fragment;


    public UtilModule(Context context)
    {
        this.context = context;
    }

    public UtilModule(Fragment fragment)
    {
        this.fragment = fragment;
    }

    @Provides
    @Named("fragmentUtilActivity")
    public FragmentUtils providesFragmentUtilForActivity(Context context)
    {
        return new FragmentUtils(context);
    }

    @Provides
    @Named("fragmentUtilFragment")
    FragmentUtils providesFragmentUtilForFragment(Fragment fragment)
    {
        return new FragmentUtils(fragment);
    }

    @Provides
    Context provideContext()
    {
        return context;
    }

    @Provides
    Fragment provideFragment()
    {
        return fragment;
    }

}

поэтому в основном я должен предоставить зависимости для моих методов, таких как контекст и фрагмент в моем случае. Затем, наконец, чтобы получить экземпляр, я должен сделать это. Например, для активности

UtilComponent component = DaggerUtilComponent.builder()
                                                     .utilModule(new UtilModule(this))
                                                     .build();
        FragmentUtils fragmentUtils = component.fragmentUtilsActivity();

Обратите внимание на .utilModule(new UtilModule(this)), так как это обеспечит контекст при построении графика.

Я очень новичок в этом кинжале, поэтому, пожалуйста, используйте этот подход с осторожностью. Гарантии/претензии отсутствуют. Удачного кинжала :)

person eC Droid    schedule 04.07.2017