From 623d3a61e0554954a0a18351a3f425320aea2122 Mon Sep 17 00:00:00 2001 From: Daniel Santiago Date: Tue, 16 Feb 2021 16:24:06 -0800 Subject: [PATCH] Perform Hilt Activity injection on a OnContextAvailableListener. Delay Hilt activity injection to a OnContextAvailableListener to enable member injecting ViewModels with SavedStateHandle. Note that this means base Hilt classes should not rely on their fields being injected before their onCreate() since injection is moved into super.onCreate() as opposed to before. RELNOTES=Delay Hilt activity injection to a OnContextAvailableListener to enable member injecting ViewModels with SavedStateHandle. To use the ContextAware APIs androidx.activity, androidx.fragment and androidx.lifecycle dependencies are updated across the Dagger libraries. PiperOrigin-RevId: 357829271 --- WORKSPACE | 8 ++-- .../processor/internal/AndroidClassNames.java | 5 +++ .../androidentrypoint/ActivityGenerator.java | 44 +++++++++++-------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 6c2b6b0ea9d..07724c9963e 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -104,10 +104,10 @@ maven_install( artifacts = [ "androidx.annotation:annotation:1.1.0", "androidx.appcompat:appcompat:1.2.0", - "androidx.activity:activity:1.1.0", - "androidx.fragment:fragment:1.2.5", - "androidx.lifecycle:lifecycle-viewmodel:2.2.0", - "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0", + "androidx.activity:activity:1.2.0", + "androidx.fragment:fragment:1.3.0", + "androidx.lifecycle:lifecycle-viewmodel:2.3.0", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.0", "androidx.multidex:multidex:2.0.1", "androidx.savedstate:savedstate:1.0.0", "androidx.test:monitor:1.1.1", diff --git a/java/dagger/hilt/android/processor/internal/AndroidClassNames.java b/java/dagger/hilt/android/processor/internal/AndroidClassNames.java index 915ae519f4b..d3709200343 100644 --- a/java/dagger/hilt/android/processor/internal/AndroidClassNames.java +++ b/java/dagger/hilt/android/processor/internal/AndroidClassNames.java @@ -113,5 +113,10 @@ public final class AndroidClassNames { public static final ClassName SAVED_STATE_HANDLE = get("androidx.lifecycle", "SavedStateHandle"); + public static final ClassName ON_CONTEXT_AVAILABLE_LISTENER = + get("androidx.activity.contextaware", "OnContextAvailableListener"); + public static final ClassName INJECT_VIA_ON_CONTEXT_AVAILABLE_LISTENER = + get("dagger.hilt.android", "InjectViaOnContextAvailableListener"); + private AndroidClassNames() {} } diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java index ce9ad14c56c..0300b56d0c6 100644 --- a/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java +++ b/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java @@ -17,9 +17,9 @@ package dagger.hilt.android.processor.internal.androidentrypoint; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeVariableName; import dagger.hilt.android.processor.internal.AndroidClassNames; @@ -56,9 +56,9 @@ public void generate() throws IOException { Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT); Processors.addGeneratedAnnotation(builder, env, getClass()); - Generators.copyConstructors(metadata.baseElement(), builder); - builder.addMethod(onCreate()); - + Generators.copyConstructors( + metadata.baseElement(), CodeBlock.builder().addStatement("init()").build(), builder); + builder.addMethod(init()); metadata.baseElement().getTypeParameters().stream() .map(TypeVariableName::get) @@ -79,23 +79,29 @@ public void generate() throws IOException { .writeTo(env.getFiler()); } - // @CallSuper - // @Override - // protected void onCreate(@Nullable Bundle savedInstanceState) { - // inject(); - // super.onCreate(savedInstanceState); + // private void init() { + // addOnContextAvailableListener(new OnContextAvailableListener() { + // @Override + // public void onContextAvailable(Context context) { + // inject(); + // } + // }); // } - private MethodSpec onCreate() { - return MethodSpec.methodBuilder("onCreate") - .addAnnotation(AndroidClassNames.CALL_SUPER) - .addAnnotation(Override.class) - .addModifiers(Modifier.PROTECTED) - .addParameter( - ParameterSpec.builder(AndroidClassNames.BUNDLE, "savedInstanceState") - .addAnnotation(AndroidClassNames.NULLABLE) + private MethodSpec init() { + return MethodSpec.methodBuilder("init") + .addModifiers(Modifier.PRIVATE) + .addStatement( + "addOnContextAvailableListener($L)", + TypeSpec.anonymousClassBuilder("") + .addSuperinterface(AndroidClassNames.ON_CONTEXT_AVAILABLE_LISTENER) + .addMethod( + MethodSpec.methodBuilder("onContextAvailable") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .addParameter(AndroidClassNames.CONTEXT, "context") + .addStatement("inject()") + .build()) .build()) - .addStatement("inject()") - .addStatement("super.onCreate(savedInstanceState)") .build(); }