Android is moving to the androidx namespace and DaggerAppCompatActivity, AndroidInjector<Fragment> and many others clash with this namespace.
Could this be added as a separate namespace for now so people using the androidx namespace can adopt it and still not be a breaking change to Dagger?
I can see there are other issues that have been opened for this same problem such as #1181, #1234, #1217, #1203 and etc.
In most issues the solution presented is to migrate to 2.16 and add to gradle.properties:
android.useAndroidX=true
android.enableJetifier=true
I have 2.17 and jetifier enabled as well, but I get the following error:
'supportFragmentInjector()' in 'com.test.ui.MainActivity' clashes with 'supportFragmentInjector()' in 'dagger.android.support.HasSupportFragmentInjector'; attempting to use incompatible return type
Android Studio complains about the missing Support V4 Fragment, that's supposed to be returned by Dagger, whereas we have now the Androidx version.
Is this an issue with jetifier?
Ok so I think I figured it out at last.
I migrated my project to Androidx and probably some of my libraries weren't properly converted by jetifier. So in order to fix this, I removed (commented) all my gradle dependencies and cleaned my project, then I made a Rebuild.
After the Rebuild I reintroduced my dependencies and did another Rebuild, so now jetifier will see "fresh" new dependencies for it to convert, and bingo, it worked, jetifier converted everything and I don't have a compilation issue anymore.
Borrowing the class and fixing the import seems to work okay in my 3 seconds of testing this. Not sure if there are any awful things that will happen with this, but feel free to borrow this code snippet:
import android.app.Activity;
import android.util.Log;
import androidx.fragment.app.Fragment;
import dagger.android.AndroidInjector;
import dagger.android.support.HasSupportFragmentInjector;
import dagger.internal.Beta;
import static android.util.Log.DEBUG;
import static dagger.internal.Preconditions.checkNotNull;
/** Injects core Android types from support libraries. */
@Beta
public final class AndroidXInjection {
private static final String TAG = "dagger.android.support";
/**
* Injects {@code fragment} if an associated {@link dagger.android.AndroidInjector} implementation
* can be found, otherwise throws an {@link IllegalArgumentException}.
*
* <p>Uses the following algorithm to find the appropriate {@code AndroidInjector<Fragment>} to
* use to inject {@code fragment}:
*
* <ol>
* <li>Walks the parent-fragment hierarchy to find the a fragment that implements {@link
* HasSupportFragmentInjector}, and if none do
* <li>Uses the {@code fragment}'s {@link Fragment#getActivity() activity} if it implements
* {@link HasSupportFragmentInjector}, and if not
* <li>Uses the {@link android.app.Application} if it implements {@link
* HasSupportFragmentInjector}.
* </ol>
*
* If none of them implement {@link HasSupportFragmentInjector}, a {@link
* IllegalArgumentException} is thrown.
*
* @throws IllegalArgumentException if no parent fragment, activity, or application implements
* {@link HasSupportFragmentInjector}.
*/
public static void inject(Fragment fragment) {
checkNotNull(fragment, "fragment");
HasSupportFragmentInjector hasSupportFragmentInjector = findHasFragmentInjector(fragment);
if (Log.isLoggable(TAG, DEBUG)) {
Log.d(
TAG,
String.format(
"An injector for %s was found in %s",
fragment.getClass().getCanonicalName(),
hasSupportFragmentInjector.getClass().getCanonicalName()));
}
AndroidInjector<Fragment> fragmentInjector =
hasSupportFragmentInjector.supportFragmentInjector();
checkNotNull(
fragmentInjector,
"%s.supportFragmentInjector() returned null",
hasSupportFragmentInjector.getClass());
fragmentInjector.inject(fragment);
}
private static HasSupportFragmentInjector findHasFragmentInjector(Fragment fragment) {
Fragment parentFragment = fragment;
while ((parentFragment = parentFragment.getParentFragment()) != null) {
if (parentFragment instanceof HasSupportFragmentInjector) {
return (HasSupportFragmentInjector) parentFragment;
}
}
Activity activity = fragment.getActivity();
if (activity instanceof HasSupportFragmentInjector) {
return (HasSupportFragmentInjector) activity;
}
if (activity.getApplication() instanceof HasSupportFragmentInjector) {
return (HasSupportFragmentInjector) activity.getApplication();
}
throw new IllegalArgumentException(
String.format("No injector was found for %s", fragment.getClass().getCanonicalName()));
}
private AndroidXInjection() {}
}
Most helpful comment
Ok so I think I figured it out at last.
I migrated my project to Androidx and probably some of my libraries weren't properly converted by
jetifier. So in order to fix this, I removed (commented) all my gradle dependencies and cleaned my project, then I made a Rebuild.After the Rebuild I reintroduced my dependencies and did another Rebuild, so now
jetifierwill see "fresh" new dependencies for it to convert, and bingo, it worked, jetifier converted everything and I don't have a compilation issue anymore.