如何使用Dagger2在Fragment中注入对BroadcastReceiver对象的创建? [英] How to inject the creation of a BroadcastReceiver object in Fragment using Dagger2?

查看:237
本文介绍了如何使用Dagger2在Fragment中注入对BroadcastReceiver对象的创建?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将 NetReceiver 对象的创建注入到片段中,但是出现以下错误:

I need to inject the creation of NetReceiver object into my Fragment but I get the following error:


错误:[Dagger / MissingBinding] com.example.myapp.NetReceiver.OnNetCallback如果没有@Provides注释的方法就无法提供。

error: [Dagger/MissingBinding] com.example.myapp.NetReceiver.OnNetCallback cannot be provided without an @Provides-annotated method.

让我告诉您我所尝试的。这是我的 NetReceiver 类:

Let me show you what I have tried. This is my NetReceiver class:

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类:

As you can see, I want to inject in the constructor a NetCallback object. I have also created a Module class that looks like this:

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

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

这是我的片段在工作时的样子:

This is how my fragment look liked when it worked:

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

这是它不工作时的样子:

And this is how it looks when it is not working:

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


推荐答案

问题是 Dagger2 不能做魔术。如何知道从何处提供 OnNetCallback 。您的片段扩展了此回调,但是其构造函数都没有使用 @Inject 注释(因为不建议您创建显式的片段构造器),也没有提供 @Provides 在模块中带有注释的方法, OnNetCallback 也不通过 MapFragment 通过 @Bind 带注释的方法,当您尝试将这样的接口与 @Qualifier 一起注入时,这是必须。

The problem is that Dagger2 cannot do magic. How it should know from where to provide a OnNetCallback. Your fragment extends this callback but neither its constructor is annotated with @Inject annotation(because you are not advised to create explicit fragment constructors) nor it is provided with @Provides annotated method in your module, nor OnNetCallback is bind with MapFragment via @Bind annotated method which is a "must be" when you trying to inject interface like this along with a @Qualifier.

但这不是主要问题。

即使您能够正确地完成所有先前的工作,它仍然不起作用,因为将存在循环依赖关系- MapFragment 取决于 NetReceiver NetReceiver 取决于 OnNetCallback OnNetCallback MapFragment ,因此 NetReceiver 取决于 MapFragment 。匕首不会允许您这样做。

Even if you will manage to do all the previous stuff correctly it will still not work because there will be a circular dependency - MapFragment depends on NetReceiver, NetReceiver depends on OnNetCallback, OnNetCallback is a MapFragment, thus NetReceiver depends on MapFragment. Dagger won't let you do it.

如果您希望您的 MapFragment 实现 OnNetCallback 我建议如下:

If you want your MapFragment to implement OnNetCallback I would suggest something like:

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

如果要注入,请单独创建一些来自 OnNetCallback Fragment 实现,并@在模块中提供并将其注入片段。

If you want it to be injected - create some separate from Fragment implementation of OnNetCallback and @Provide it in module and inject it into fragment.

@ContributesAndroidInjector 应该用于喷射器,但不能用于喷射器-它告诉 Dagger 该类应该注入一些用 @Inject @Provides @Bind 批注。

Also @ContributesAndroidInjector should be used for the injeters but not for the injectees - it tells Dagger that this class should be injected with some stuff described with @Inject, @Provides and @Bind annotations.

我也建议您阅读官方指南关于 Dagger2 其在Android中的用法

Also I would recommend you to read an official guide regarding Dagger2 and its usage for Android.

希望有帮助。

这篇关于如何使用Dagger2在Fragment中注入对BroadcastReceiver对象的创建?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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