Reputation: 272
I need to inject the creation of NetReceiver
object into my Fragment but I get the following error:
error: [Dagger/MissingBinding] com.example.myapp.NetReceiver.OnNetCallback cannot be provided without an @Provides-annotated method.
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);
}
}
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);
}
}
Upvotes: 1
Views: 2723
Reputation: 16729
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
.
But that is not the main issue.
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.
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);
}
}
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.
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.
Also I would recommend you to read an official guide regarding Dagger2
and its usage for Android.
Hope it helps.
Upvotes: 1