CROSP
CROSP

Reputation: 4617

Dagger 2 Module Override in Subcomponent

I have app with Subcomponents like this

-------- ApplicationComponent ------------
        |                    |
        |                    |
        |                    |
    Service Component      Activity Component
                              |
                              |
                              |
                           Fragment Component

Everything works fine, but I want to do one thing. Android Mrequires runtime permissions so I decided to createController, something like helper class that will be injected intoFragmentorActivity` Common Interface

public interface PermissionController {

    boolean hasPermissionInManifest(String permissionName);

    boolean isPermissionGranted(String permission);

/**
 * Request permission for Android 6
 *
 * @param permission  permission that is requested
 * @param requestCode request code
 * @return if user is going to be asked about permission so we need to handle callback, otherwise
 * user was already asked or permission is not required cause of android lower version
 */
boolean requestPermission(int requestCode, String permission);

    void requestPermissions(int requestCode, String... permissions);

}

And one method from different implementations PermissionActivityManager and PermissionFragmentManager

   @Override
    public boolean requestPermission(int requestCode, String permission) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (mContext.checkSelfPermission(permission)
                    != PackageManager.PERMISSION_GRANTED) {
                mContext.requestPermissions(new String[]{permission},
                        requestCode);
                return true;
            }
        }
        return false;
    }

And Fragment implementation

   @Override
    public boolean requestPermission(int requestCode, String permission) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(mFragment.getActivity(), permission)
                    != PackageManager.PERMISSION_GRANTED) {
                mFragment.requestPermissions(new String[]{permission},
                        requestCode);
                return true;
            }
        }
        return false;
    }

Hope you got an idea.

But about the problem, my FragmentComponent is subcomponent of ActivityComponent

They both have PermissionModule

@PerActivity
@Subcomponent(
        modules = {
                ActivityModule.class,
                PermissionModule.class
        })
public interface ActivityComponent {
    Activity activity();

    FragmentComponent fragmentComponent(FragmentModule module);

    void inject(BaseActivity baseActivity);

    void inject(MainAppActivity mainAppActivity);

}

And for Fragment

@Subcomponent(
        modules = {
                FragmentModule.class,
                ProviderModule.class,
                PermissionModule.class
        })
@PerFragment
public interface FragmentComponent {
    Fragment fragment();

    void inject(BaseFragment baseFragment);

}

And modules are the same except annotations and returned instances.

@PerFragment
@Module
public class PermissionModule {
    @PerFragment
    @Provides
    PermissionController providePermissionController(Fragment fragment) {
        return new PermissionFragmentManager(fragment);
    }
}

@PerActivity
@Module
public class PermissionModule {
    @PerActivity
    @Provides
    PermissionController providePermissionController(Activity activity) {
        return new PermissionActivityManager(activity);
    }
}

So my question is - if there is any way to override provide method used in parent component or there is another way to solve the problem ? Because in my case PermissionActivityManager was injected.

Upvotes: 1

Views: 2022

Answers (1)

EpicPandaForce
EpicPandaForce

Reputation: 81539

@Subcomponent inherits all bindings from the superscoped component. In this case, that is the @ActivityScope component.

If you want to control the inherited dependencies, you have to use Component Dependencies. Component dependencies allow you to inherit only the bindings specified by the provision methods.

If you don't want to tinker with new builders, then I'd recommend using @Named("activity") and @Named("fragment") annotation to specify the type of permission handler you'd like to inject. You have to put it on your @Inject annotated field and on the @Provides annotated method.

Upvotes: 2

Related Questions