-1

I need to inject an "RxPermissions" RX Permissions lib instance to my fragment. Its my (basic) fragment class:

public class MapFragment extends Fragment {  
  //an empty ctor

  @Inject
  RxPermissions rxPermissions; //need inject.

  @Override
  public void onAttach(Context context) {
      AndroidSupportInjection.inject(this); //for injection
      super.onAttach(context);
  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //When i not use injection for rxPermissions -> rxPermissions = new RxPermissions(getActivity());
    if(rxPermission.isGranted(Manifest.permission.ACCESS_FINE_LOCATION)){
       ///TODO: implement isGranted logic
    }
  }
}

Here is my MapFragmentSubComponent and MapFragmentSubModule for inject into MapFragment:

@Subcomponent
public interface MapFragmentSubComponent extends AndroidInjector<MapFragment> {

    @Subcomponent.Builder
    public abstract class Builder extends AndroidInjector.Builder<MapFragment>{

  }
}


@Module(subcomponents = MapFragmentSubComponent.class)
public abstract class MapFragmentSubModule {

   @Binds
   @IntoMap
   @FragmentKey(MapFragment.class)
   abstract AndroidInjector.Factory<? extends Fragment> bindMapFragmentInjectorFactory(MapFragmentSubComponent.Builder builder);

   //Contains here my provider method for example viewmodelfactory provide.

   //I need (i think) provide rxPermissions here. but how ?

  }

And MapFragmentSubModule installed at AppComponent with @Component(modules = {MapFragmentSubmodule.class})

So how can i inject RxPermissions to fragment or other? (ex activity ?)

Update for @Jeff Bowman Jun 29 at 18:39 comment: So. I inject activity hash in MainActivity (it's work) but that's not inherited in MapFragment. Can i resolve this problem with dagger-android lib ? (Or use old fashion style dagger 2 implementation for that problem resolving? ) Here is my error msg:

    error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)]   java.lang.Integer cannot be provided without an @Inject constructor or an @Provides-annotated method.
java.lang.Integer is injected at
.ui.main.map.MapFragment.activityHash
.ui.main.map.MapFragment is injected at
dagger.android.AndroidInjector.inject(T)
component path: .component.AppComponent ? .module.BuildersModule_BindMapFragment.MapFragmentSubcomponent

So i need activityHash from MainActivityModule in MapFragment.

  • Update: So i inject a variable in application. Can i use this in activity or fragment? And i inject a variable in activity can i use this in fragment ? – Dancs Berci Jun 28 '18 at 13:57

1 Answers1

0

If your MapFragmentSubModule is included in an Activity subcomponent using dagger.android, then you'll have access in your MapFragmentSubModule to the specific Activity subclass that you're injecting.

@Module(subcomponents = MapFragmentSubComponent.class)
public abstract class MapFragmentSubModule {
  // ...

  // You probably want @ActivityScope; see below.
  @Provides static RxPermissions provideRxPermissions(YourActivity activity) {
    return new RxPermissions(activity);
  }
}

Note that dagger.android will only be able to inject your subclass YourActivity, not Activity itself. This is partly for consistency: Fragments can be nested inside other Fragments (such that injecting Fragment would be ambiguous if the superclass bindings were automatic). For less-ambiguous bindings, you may want @Binds Activity bindActivity(YourActivity activity).

If you don't have an Activity subcomponent, you'll need to fetch the Activity out of the Fragment, which means installing RxPermissions on the Fragment subcomponent instead.

@Subcomponent(modules = MapFragmentSubComponent.Module.class)
public interface MapFragmentSubComponent extends AndroidInjector<MapFragment> {
  @Subcomponent.Builder
  public abstract class Builder extends AndroidInjector.Builder<MapFragment> {    
  }

  @dagger.Module public abstract class Module {
    @Provides static RxPermissions provideRxPermissions(MapFragment fragment) {
      return new RxPermissions(fragment.getActivity());
    }
  }
}

That said, I assume you'll want the RxPermissions object to be consistent within the Activity, which means using an Activity-scoped subcomponent (creating one if necessary) and annotating your @Provides method with @ActivityScope or whatever you've named your activity subcomponent scope annotation.

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Use include tag at MainActivitySubComponent ? Or with "module = MapFragmentSubModule.class" ? at Subcomponent annotation ? I tested with module tags. But i have this error: A binding with matching key exists in component: MainActivitySubComponent. So i remove MapFragmentSubModule installation from AppComponent. I have no injector factory error. And ofcourse MainActivity cannot be provided without an @Inject constructor or an Provides-annotated method. I remove MainActivitySubModule from AppComponent: and has MainActivity cannot provided without Inject ctor. – Dancs Berci Jun 29 '18 at 07:47
  • An additional question: Can i reach activity graph in fragment ? Ofcourse with dagger-android. – Dancs Berci Jun 29 '18 at 12:19
  • @DancsBerci Please paste in your actual Dagger compiler error into your question, as an edit. The way you've summarized it, it's impossible for me to tell which binding has been duplicated or what your real problem is. – Jeff Bowman Jun 29 '18 at 18:39
  • I updated my original question with "update" section :) – Dancs Berci Jul 04 '18 at 08:23
  • @DancsBerci Thank you! Now please show us where/how you install MapFragmentSubModule, and you should be good to go. If you're using `@ContributesAndroidInjector` on your Activity, you should be installing it on the `modules` list there; if you've made your own subcomponent in dagger.android style, you should add it onto your activity _subcomponent_. MapFragmentSubModule should _not_ be on AppComponent in any case; it should be on your Activity subcomponent so it can consume Activity bindings. – Jeff Bowman Jul 05 '18 at 17:42
  • My MapFragmentSubModule installed in my BuildersModule class: ContributesAndroidInjector(modules = {MapFragmentSubModule.class}) abstract MapFragment bindMapFragment(); (And same install in this module for MainActivitySubModule) And BuildersModule installed in AppComponent modules list. But i can't inject an integer value to MapFragment from MainActivitySubModule provider :( – Dancs Berci Jul 06 '18 at 14:20
  • @Dancs Don't install MapFragmentSubModule in BuildersModule. Only install it in your `@ContributesAndroidInjector` binding as you showed me here. – Jeff Bowman Jul 06 '18 at 15:53
  • I only install MapFragmentSubModule at ContributesAndroidInjector(modules = .... etc) but this line in the BuildersModule. And if not install MapFragmentSubModule in ContributesAndroidInjector i got a new compiler error: xy variable cannot be provided without provider method... (ofc, because not connected the SubModule with SubComponent because i not install mapfragmentsubmodule at Contribute.... So, can you show me a working example project for my problem? – Dancs Berci Jul 09 '18 at 07:13
  • @Dancs No; SO is not a code-writing service. If anything it is the asker's responsibility to post their own [MCVE](https://stackoverflow.com/help/mcve). I answered your question, and after many scattershot follow-ups drifting far away from RxPermissions you ask me for an entire working example project. Best of luck. – Jeff Bowman Jul 09 '18 at 08:18
  • All right. I'm sorry I took your time. Thanks for the all of help. Best of luck! – Dancs Berci Jul 09 '18 at 08:32