Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt the new androidx namespace #1264

Closed
feinstein opened this issue Aug 28, 2018 · 3 comments · Fixed by #1726
Closed

Adopt the new androidx namespace #1264

feinstein opened this issue Aug 28, 2018 · 3 comments · Fixed by #1726

Comments

@feinstein
Copy link

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?

@feinstein
Copy link
Author

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?

@feinstein
Copy link
Author

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.

@CodyEngel
Copy link

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() {}
}

ZacSweers added a commit to ZacSweers/dagger that referenced this issue Jan 17, 2020
Resolves google#1652
Resolves google#1619
Resolves google#1248
Resolves google#1489
Resolves google#1444
Resolves google#1313
Resolves google#1264

Enables better support for newer androidx subprojects like google#1271, but I feel we need to start somewhere. This unblocks that by making the initial move to androidx as a namespace, and then splitting up newer artifacts out of this (and progressively making dagger-android-support increasingly just a shim that delegates to them) is a healthy approach.
cpovirk pushed a commit that referenced this issue Jan 28, 2020
Update imports and dependencies to use AndroidX APIs.
For backwards compatibility, produce two new artifacts,
"dagger-android-legacy" and "dagger-android-support-legacy" that are
dejetified artifacts of the AndroidX versions.

Resolves #1652
Resolves #1619
Resolves #1489
Resolves #1444
Resolves #1313
Resolves #1271
Resolves #1248
Resolves #1264

Co-authored-by: Zac Sweers <zsweers@slack-corp.com>

RELNOTES=Migrate dagger-android to AndroidX.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=291051989
danysantiago added a commit that referenced this issue Jan 28, 2020
Update imports and dependencies to use AndroidX APIs.
For backwards compatibility, produce two new artifacts,
"dagger-android-legacy" and "dagger-android-support-legacy" that are
dejetified artifacts of the AndroidX versions.

Resolves #1652
Resolves #1619
Resolves #1489
Resolves #1444
Resolves #1313
Resolves #1271
Resolves #1248
Resolves #1264

Co-authored-by: Zac Sweers <zsweers@slack-corp.com>

RELNOTES=Migrate dagger-android to AndroidX.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=291051989
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants