Как внедрить создание объекта BroadcastReceiver во Fragment с помощью Dagger2? - PullRequest
0 голосов
/ 07 ноября 2019

Мне нужно добавить объект NetReceiver в мой фрагмент, но я получаю следующую ошибку:

ошибка: [Dagger / MissingBinding] com.example.myapp.NetReceiver.OnNetCallback не можетпредоставляется без аннотируемого метода @ Provides.

Позвольте мне показать вам, что я пробовал. Это мой NetReceiver класс:

public class NetReceiver extends BroadcastReceiver {
    private OnNetCallback onNetCallback;

    @Inject
    public NetReceiver(OnNetCallback onNetCallback) {
        this.onNetCallback = onNetCallback;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (someCondition) {
            onNetCallback.enableOperation(true);
        }
    }

    public interface OnNetCallback {
        void enableOperation(boolean isOk);
    }
}

Как видите, я хочу добавить в конструктор объект NetCallback. Я также создал класс Module, который выглядит следующим образом:

@Module
public abstract class NetReceiverModule {
    @ContributesAndroidInjector //Error?!?!?!?!
    abstract NetReceiver.OnNetCallback provideOnNetCallback();

    @Singleton
    @Provides
    static NetReceiver provideNetReceiver(NetReceiver.OnNetCallback onNetCallback) {
        return new NetReceiver(onNetCallback);
    }
}

Вот так выглядит мой фрагмент, когда он работал:

public class MapFragment extends Fragment implements NetReceiver.OnNetCallback {
    private NetReceiver netReceiver;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //Inflate View
        netReceiver = new NetReceiver(this); //Worked
    }

    @Override
    public void onResume() {
    super.onResume();
        mainActivity.registerReceiver(netReceiver, intentFilter);
    }

    @Override
    public void onPause() {
    super.onPause();
        mainActivity.unregisterReceiver(netReceiver);
    }
}

И вот так он выглядит, когда он работает. не работает:

public class MapFragment extends DaggerFragment implements NetReceiver.OnNetCallback {
    @Inject NetReceiver netReceiver;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //Inflate View
        //netReceiver = new NetReceiver(this); //Worked
    }

    @Override
    public void onResume() {
    super.onResume();
        mainActivity.registerReceiver(netReceiver, intentFilter);
    }

    @Override
    public void onPause() {
    super.onPause();
        mainActivity.unregisterReceiver(netReceiver);
    }
}

1 Ответ

1 голос
/ 07 ноября 2019

Проблема в том, что Dagger2 не может творить магию. Как следует знать, откуда предоставить OnNetCallback. Ваш фрагмент расширяет этот обратный вызов, но ни его конструктор не аннотирован @Inject аннотацией (потому что вам не рекомендуется создавать явные конструкторы фрагментов), ни он не снабжен аннотированным методом @Provides в вашем модуле, а OnNetCallback не связан с MapFragment через @Bind аннотированный метод, который «должен быть», когда вы пытаетесь ввести интерфейс, подобный этому, вместе с @Qualifier.

Но это не главная проблема.

Даже если вам удастся сделать все предыдущие вещи правильно, он все равно не будет работать, потому что будет круговая зависимость - MapFragment зависит от NetReceiver, NetReceiver зависит от OnNetCallback, OnNetCallback - это MapFragment, таким образом, NetReceiver зависит от MapFragment. Кинжал не позволит вам сделать это.

Если вы хотите, чтобы ваш MapFragment реализовал OnNetCallback, я бы предложил что-то вроде:

public class NetReceiver extends BroadcastReceiver {

    public OnNetCallback onNetCallback;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (someCondition && onNetCallback!= null) {
            onNetCallback.enableOperation(true);
        }
    }

    public interface OnNetCallback {
        void enableOperation(boolean isOk);
    }
}


public class MapFragment extends DaggerFragment implements NetReceiver.OnNetCallback {

    @Inject NetReceiver netReceiver;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //Inflate View
        netReceiver.onNetCallback = this
    }

    @Override
    public void onResume() {
    super.onResume();
        mainActivity.registerReceiver(netReceiver, intentFilter);
    }

    @Override
    public void onPause() {
    super.onPause();
        mainActivity.unregisterReceiver(netReceiver);
    }
}

Если вы хотите, чтобы его вводили -создайте отдельную от Fragment реализацию OnNetCallback и @ предоставьте ее в модуле и вставьте ее во фрагмент.

Также @ContributesAndroidInjector следует использовать для инжекторов, но не для инжекторов - это говорит Dagger что этот класс должен быть добавлен с некоторыми вещами, описанными с аннотациями @Inject, @Provides и @Bind.

Также я бы порекомендовал вам прочитать официальное руководство относительно Dagger2 и его использования для Android .

Надеюсь, это поможет.

...