diff --git a/java/dagger/hilt/android/BUILD b/java/dagger/hilt/android/BUILD index abbdbc7b150..b30f6625dd3 100644 --- a/java/dagger/hilt/android/BUILD +++ b/java/dagger/hilt/android/BUILD @@ -262,7 +262,6 @@ gen_maven_artifact( proguard_and_r8_specs = [ "//java/dagger/hilt:proguard-rules.pro", "//java/dagger/hilt/android:proguard-rules.pro", - "//java/dagger/hilt/android/lifecycle:proguard-rules.pro", "//java/dagger/hilt/internal:proguard-rules.pro", ], ) diff --git a/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java b/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java index 78b8eb16b8f..67e68e71af6 100644 --- a/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java +++ b/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java @@ -29,7 +29,7 @@ import dagger.hilt.android.components.FragmentComponent; import dagger.hilt.android.internal.builders.ViewModelComponentBuilder; import dagger.multibindings.Multibinds; -import java.util.Set; +import java.util.Map; import javax.inject.Inject; /** @@ -69,12 +69,12 @@ public static ViewModelProvider.Factory getFragmentFactory( /** Internal factory for the Hilt ViewModel Factory. */ public static final class InternalFactoryFactory { - private final Set keySet; + private final Map, Boolean> keySet; private final ViewModelComponentBuilder viewModelComponentBuilder; @Inject InternalFactoryFactory( - @HiltViewModelMap.KeySet Set keySet, + @HiltViewModelMap.KeySet Map, Boolean> keySet, ViewModelComponentBuilder viewModelComponentBuilder) { this.keySet = keySet; this.viewModelComponentBuilder = viewModelComponentBuilder; @@ -103,7 +103,7 @@ private ViewModelProvider.Factory getHiltViewModelFactory( interface ActivityModule { @Multibinds @HiltViewModelMap.KeySet - abstract Set viewModelKeys(); + abstract Map, Boolean> viewModelKeys(); } /** The activity entry point to retrieve the factory. */ diff --git a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java index 33b1618031d..6819c24bd20 100644 --- a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java +++ b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java @@ -35,7 +35,6 @@ import dagger.hilt.android.internal.builders.ViewModelComponentBuilder; import dagger.multibindings.Multibinds; import java.util.Map; -import java.util.Set; import javax.inject.Provider; import kotlin.jvm.functions.Function1; @@ -55,11 +54,11 @@ public final class HiltViewModelFactory implements ViewModelProvider.Factory { @InstallIn(ViewModelComponent.class) public interface ViewModelFactoriesEntryPoint { @HiltViewModelMap - Map> getHiltViewModelMap(); + Map, Provider> getHiltViewModelMap(); // From ViewModel class names to user defined @AssistedFactory-annotated implementations. @HiltViewModelAssistedMap - Map getHiltViewModelAssistedMap(); + Map, Object> getHiltViewModelAssistedMap(); } /** Creation extra key for the callbacks that create @AssistedInject-annotated ViewModels. */ @@ -72,19 +71,19 @@ public interface ViewModelFactoriesEntryPoint { interface ViewModelModule { @Multibinds @HiltViewModelMap - Map hiltViewModelMap(); + Map, ViewModel> hiltViewModelMap(); @Multibinds @HiltViewModelAssistedMap - Map hiltViewModelAssistedMap(); + Map, Object> hiltViewModelAssistedMap(); } - private final Set hiltViewModelKeys; + private final Map, Boolean> hiltViewModelKeys; private final ViewModelProvider.Factory delegateFactory; private final ViewModelProvider.Factory hiltViewModelFactory; public HiltViewModelFactory( - @NonNull Set hiltViewModelKeys, + @NonNull Map, Boolean> hiltViewModelKeys, @NonNull ViewModelProvider.Factory delegateFactory, @NonNull ViewModelComponentBuilder viewModelComponentBuilder) { this.hiltViewModelKeys = hiltViewModelKeys; @@ -113,12 +112,12 @@ private T createViewModel( Provider provider = EntryPoints.get(component, ViewModelFactoriesEntryPoint.class) .getHiltViewModelMap() - .get(modelClass.getName()); + .get(modelClass); Function1 creationCallback = extras.get(CREATION_CALLBACK_KEY); Object assistedFactory = EntryPoints.get(component, ViewModelFactoriesEntryPoint.class) .getHiltViewModelAssistedMap() - .get(modelClass.getName()); + .get(modelClass); if (assistedFactory == null) { if (creationCallback == null) { @@ -167,7 +166,7 @@ private T createViewModel( @Override public T create( @NonNull Class modelClass, @NonNull CreationExtras extras) { - if (hiltViewModelKeys.contains(modelClass.getName())) { + if (hiltViewModelKeys.containsKey(modelClass)) { return hiltViewModelFactory.create(modelClass, extras); } else { return delegateFactory.create(modelClass, extras); @@ -177,7 +176,7 @@ public T create( @NonNull @Override public T create(@NonNull Class modelClass) { - if (hiltViewModelKeys.contains(modelClass.getName())) { + if (hiltViewModelKeys.containsKey(modelClass)) { return hiltViewModelFactory.create(modelClass); } else { return delegateFactory.create(modelClass); @@ -188,7 +187,8 @@ public T create(@NonNull Class modelClass) { @InstallIn(ActivityComponent.class) interface ActivityCreatorEntryPoint { @HiltViewModelMap.KeySet - Set getViewModelKeys(); + Map, Boolean> getViewModelKeys(); + ViewModelComponentBuilder getViewModelComponentBuilder(); } diff --git a/java/dagger/hilt/android/lifecycle/BUILD b/java/dagger/hilt/android/lifecycle/BUILD index 4452c35a908..26394f0f8b4 100644 --- a/java/dagger/hilt/android/lifecycle/BUILD +++ b/java/dagger/hilt/android/lifecycle/BUILD @@ -33,7 +33,6 @@ android_library( exported_plugins = [ "//java/dagger/hilt/android/processor/internal/viewmodel:processor", ], - proguard_specs = ["proguard-rules.pro"], exports = [ "//:dagger_with_compiler", "//java/dagger/hilt:install_in", diff --git a/java/dagger/hilt/android/lifecycle/proguard-rules.pro b/java/dagger/hilt/android/lifecycle/proguard-rules.pro deleted file mode 100644 index 6c647f10532..00000000000 --- a/java/dagger/hilt/android/lifecycle/proguard-rules.pro +++ /dev/null @@ -1,2 +0,0 @@ -# Keep class names of Hilt injected ViewModels since their name are used as a multibinding map key. --keepnames @dagger.hilt.android.lifecycle.HiltViewModel class * extends androidx.lifecycle.ViewModel \ No newline at end of file diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt index e7b3dad2f2f..6a156fa7925 100644 --- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt +++ b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt @@ -42,18 +42,20 @@ import javax.lang.model.element.Modifier * public static abstract class BindsModule { * @Binds * @IntoMap - * @StringKey("pkg.$") + * @LazyClassKey(pkg.$) * @HiltViewModelMap * public abstract ViewModel bind($ vm) * } * @Module * @InstallIn(ActivityRetainedComponent.class) * public static final class KeyModule { + * private static String className = "pkg.$"; * @Provides - * @IntoSet + * @IntoMap * @HiltViewModelMap.KeySet - * public static String provide() { - * return "pkg.$"; + * @LazyClassKey(pkg.$) + * public static boolean provide() { + * return true; * } * } * } @@ -62,7 +64,7 @@ import javax.lang.model.element.Modifier @OptIn(ExperimentalProcessingApi::class) internal class ViewModelModuleGenerator( private val processingEnv: XProcessingEnv, - private val viewModelMetadata: ViewModelMetadata + private val viewModelMetadata: ViewModelMetadata, ) { fun generate() { val modulesTypeSpec = @@ -75,7 +77,7 @@ internal class ViewModelModuleGenerator( .addMember( "topLevelClass", "$T.class", - viewModelMetadata.className.topLevelClassName() + viewModelMetadata.className.topLevelClassName(), ) .build() ) @@ -94,7 +96,7 @@ internal class ViewModelModuleGenerator( private fun getBindsModuleTypeSpec() = createModuleTypeSpec( className = "BindsModule", - component = AndroidClassNames.VIEW_MODEL_COMPONENT + component = AndroidClassNames.VIEW_MODEL_COMPONENT, ) .addModifiers(Modifier.ABSTRACT) .addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build()) @@ -112,8 +114,8 @@ internal class ViewModelModuleGenerator( .addAnnotation(ClassNames.BINDS) .addAnnotation(ClassNames.INTO_MAP) .addAnnotation( - AnnotationSpec.builder(ClassNames.STRING_KEY) - .addMember("value", S, viewModelMetadata.className.reflectionName()) + AnnotationSpec.builder(ClassNames.LAZY_CLASS_KEY) + .addMember("value", "$T.class", viewModelMetadata.className) .build() ) .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_MAP_QUALIFIER) @@ -125,7 +127,7 @@ internal class ViewModelModuleGenerator( private fun getKeyModuleTypeSpec() = createModuleTypeSpec( className = "KeyModule", - component = AndroidClassNames.ACTIVITY_RETAINED_COMPONENT + component = AndroidClassNames.ACTIVITY_RETAINED_COMPONENT, ) .addModifiers(Modifier.FINAL) .addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build()) @@ -135,11 +137,16 @@ internal class ViewModelModuleGenerator( private fun getViewModelKeyProvidesMethod() = MethodSpec.methodBuilder("provide") .addAnnotation(ClassNames.PROVIDES) - .addAnnotation(ClassNames.INTO_SET) + .addAnnotation(ClassNames.INTO_MAP) + .addAnnotation( + AnnotationSpec.builder(ClassNames.LAZY_CLASS_KEY) + .addMember("value", "$T.class", viewModelMetadata.className) + .build() + ) .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_KEYS_QUALIFIER) .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .returns(String::class.java) - .addStatement("return $S", viewModelMetadata.className.reflectionName()) + .returns(Boolean::class.java) + .addStatement("return true") .build() /** @@ -147,7 +154,7 @@ internal class ViewModelModuleGenerator( * ``` * @Binds * @IntoMap - * @StringKey("pkg.FooViewModel") + * @LazyClassKey(pkg.FooViewModel.class) * @HiltViewModelAssistedMap * public abstract Object bind(FooViewModelAssistedFactory factory); * ``` @@ -160,8 +167,8 @@ internal class ViewModelModuleGenerator( .addAnnotation(ClassNames.BINDS) .addAnnotation(ClassNames.INTO_MAP) .addAnnotation( - AnnotationSpec.builder(ClassNames.STRING_KEY) - .addMember("value", S, viewModelMetadata.className.reflectionName()) + AnnotationSpec.builder(ClassNames.LAZY_CLASS_KEY) + .addMember("value", "$T.class", viewModelMetadata.className) .build() ) .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_ASSISTED_FACTORY_MAP_QUALIFIER) diff --git a/java/dagger/hilt/processor/internal/ClassNames.java b/java/dagger/hilt/processor/internal/ClassNames.java index 26b90a448e4..00de786f0a3 100644 --- a/java/dagger/hilt/processor/internal/ClassNames.java +++ b/java/dagger/hilt/processor/internal/ClassNames.java @@ -72,6 +72,9 @@ public final class ClassNames { public static final ClassName DEFINE_COMPONENT_CLASSES = get("dagger.hilt.internal.definecomponent", "DefineComponentClasses"); + public static final ClassName IDENTIFIER_NAME_STRING = + get("dagger.internal", "IdentifierNameString"); + public static final ClassName ASSISTED_INJECT = get("dagger.assisted", "AssistedInject"); public static final ClassName ASSISTED_FACTORY = get("dagger.assisted", "AssistedFactory"); public static final ClassName BINDS = @@ -86,6 +89,7 @@ public final class ClassNames { public static final ClassName INTO_SET = get("dagger.multibindings", "IntoSet"); public static final ClassName ELEMENTS_INTO_SET = get("dagger.multibindings", "ElementsIntoSet"); public static final ClassName STRING_KEY = get("dagger.multibindings", "StringKey"); + public static final ClassName LAZY_CLASS_KEY = get("dagger.multibindings", "LazyClassKey"); public static final ClassName PROVIDES = get("dagger", "Provides"); public static final ClassName COMPONENT = get("dagger", "Component"); diff --git a/java/dagger/internal/IdentifierNameString.java b/java/dagger/internal/IdentifierNameString.java index 7d4b1d9e45e..95d2bfa6fa8 100644 --- a/java/dagger/internal/IdentifierNameString.java +++ b/java/dagger/internal/IdentifierNameString.java @@ -26,8 +26,9 @@ /** * Annotates the dagger generated class that requires applying -identifiernamestring rule. * - *

When applied, all the strings that corresponds to a class name within the annotated class will - * be obfuscated if its corresponding class is obfuscated. This only works with r8. This annotation + *

When applied, all the strings fields that corresponds to a class name within the annotated + * class will be obfuscated if its corresponding class is obfuscated. This only works with r8. + * */ @Documented @Retention(CLASS)