Skip to content

Commit

Permalink
Adds the dagger.hilt.android.useFragmentGetContextFix flag to guard t…
Browse files Browse the repository at this point in the history
…he corrected Fragment.getContext() behavior.

RELNOTES=Adds the dagger.hilt.android.useFragmentGetContextFix flag to guard the corrected Fragment.getContext() behavior
PiperOrigin-RevId: 375801929
  • Loading branch information
Chang-Eric authored and Dagger Team committed May 25, 2021
1 parent 9bfc67e commit 5ce0cea
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ java_library(
"//java/dagger/hilt/android/processor/internal:android_classnames",
"//java/dagger/hilt/android/processor/internal:utils",
"//java/dagger/hilt/processor/internal:classnames",
"//java/dagger/hilt/processor/internal:compiler_options",
"//java/dagger/hilt/processor/internal:component_names",
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package dagger.hilt.android.processor.internal.androidentrypoint;

import static dagger.hilt.processor.internal.HiltCompilerOptions.useFragmentGetContextFix;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
Expand Down Expand Up @@ -176,12 +178,21 @@ private MethodSpec initializeComponentContextMethod() {
// initializeComponentContext();
// return componentContext;
// }
private static MethodSpec getContextMethod() {
return MethodSpec.methodBuilder("getContext")
private MethodSpec getContextMethod() {
MethodSpec.Builder builder = MethodSpec.methodBuilder("getContext")
.returns(AndroidClassNames.CONTEXT)
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.beginControlFlow("if (super.getContext() == null)")
.addModifiers(Modifier.PUBLIC);

if (useFragmentGetContextFix(env)) {
builder.beginControlFlow("if (super.getContext() == null)");
} else {
builder.beginControlFlow(
"if (super.getContext() == null && $N == null)",
COMPONENT_CONTEXT_FIELD);
}

return builder
.addStatement("return null")
.endControlFlow()
.addStatement("initializeComponentContext()")
Expand Down
14 changes: 13 additions & 1 deletion java/dagger/hilt/processor/internal/HiltCompilerOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ public static boolean useAggregatingRootProcessor(ProcessingEnvironment env) {
return BooleanOption.USE_AGGREGATING_ROOT_PROCESSOR.get(env);
}

/**
* Returns {@code true} if fragment code should use the fixed getContext() behavior where it
* correctly returns null after a fragment is removed. This fixed behavior matches the behavior
* of a regular fragment and can help catch issues where a removed or leaked fragment is
* incorrectly used.
*/
public static boolean useFragmentGetContextFix(ProcessingEnvironment env) {
return BooleanOption.USE_FRAGMENT_GET_CONTEXT_FIX.get(env);
}

/** Processor options which can have true or false values. */
private enum BooleanOption {
/** Do not use! This is for internal use only. */
Expand All @@ -97,7 +107,9 @@ private enum BooleanOption {

DISABLE_MODULES_HAVE_INSTALL_IN_CHECK("disableModulesHaveInstallInCheck", false),

SHARE_TEST_COMPONENTS("shareTestComponents", false);
SHARE_TEST_COMPONENTS("shareTestComponents", false),

USE_FRAGMENT_GET_CONTEXT_FIX("android.useFragmentGetContextFix", false);

private final String name;
private final boolean defaultValue;
Expand Down
12 changes: 12 additions & 0 deletions javatests/dagger/hilt/android/FragmentContextOnAttachTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,16 @@ public void testGetContextAvailableBeforeSuperOnAttach() throws Exception {
assertThat(fragment.onAttachContextContext).isNotNull();
assertThat(fragment.onAttachActivityContext).isNotNull();
}

// Tests the default behavior of the useFragmentGetContextFix flag. Current default is false
// so this tests the broken behavior.
@Test
public void testGetContextDoesNotReturnNullAfterRemoval() throws Exception {
FragmentActivity activity = Robolectric.setupActivity(TestActivity.class);
TestFragment fragment = new TestFragment();
activity.getSupportFragmentManager().beginTransaction().add(fragment, "").commitNow();
assertThat(fragment.getContext()).isNotNull();
activity.getSupportFragmentManager().beginTransaction().remove(fragment).commitNow();
assertThat(fragment.getContext()).isNotNull();
}
}

0 comments on commit 5ce0cea

Please sign in to comment.