Ensure AndroidViewBinding+Fragments work after recreate
When a Fragment is inflated via AndroidViewBinding,
it should consistently be attached to the view hierarchy
even after a configuration change.
By adding an implementation dependency on a new enough
version of fragments that fixes the underlying issue,
we can ensure that AndroidViewBinding always works.
Relnote: "Compose ViewBinding now depends on
[Fragment `1.3.2`](/jetpack/androidx/releases/fragment#1.3.2)
and now consistently shows fragments inflated via
`FragmentContainerView` after configuration changes."
Test: new FragmentRecreateTest
BUG: 179915946
Change-Id: I0743d383564ee28429ad0074f58de79c0e98ada0
diff --git a/compose/ui/ui-viewbinding/build.gradle b/compose/ui/ui-viewbinding/build.gradle
index a364142..2389015 100644
--- a/compose/ui/ui-viewbinding/build.gradle
+++ b/compose/ui/ui-viewbinding/build.gradle
@@ -32,6 +32,9 @@
implementation(KOTLIN_STDLIB)
implementation(project(":compose:ui:ui"))
implementation(VIEW_BINDING)
+ // Required to ensure that Fragments inflated by AndroidViewBinding
+ // actually appear after configuration changes
+ implementation("androidx.fragment:fragment-ktx:1.3.2")
androidTestImplementation(project(":compose:foundation:foundation"))
androidTestImplementation(project(":compose:test-utils"))
diff --git a/compose/ui/ui-viewbinding/samples/build.gradle b/compose/ui/ui-viewbinding/samples/build.gradle
index 7c56671e..a73c3a1 100644
--- a/compose/ui/ui-viewbinding/samples/build.gradle
+++ b/compose/ui/ui-viewbinding/samples/build.gradle
@@ -34,9 +34,13 @@
implementation(project(":compose:runtime:runtime"))
implementation(project(":compose:ui:ui"))
implementation(project(":compose:ui:ui-viewbinding"))
+ // Used when creating layouts that contain a FragmentContainerView
+ implementation("androidx.fragment:fragment-ktx:1.3.2")
androidTestImplementation(project(":compose:foundation:foundation"))
androidTestImplementation(project(":compose:test-utils"))
+ androidTestImplementation(project(":activity:activity-compose"))
+ androidTestImplementation(project(":internal-testutils-runtime"))
androidTestImplementation(ANDROIDX_TEST_RUNNER)
androidTestImplementation(JUNIT)
androidTestImplementation(TRUTH)
diff --git a/compose/ui/ui-viewbinding/samples/src/androidTest/AndroidManifest.xml b/compose/ui/ui-viewbinding/samples/src/androidTest/AndroidManifest.xml
index f1cd514a..490955b 100644
--- a/compose/ui/ui-viewbinding/samples/src/androidTest/AndroidManifest.xml
+++ b/compose/ui/ui-viewbinding/samples/src/androidTest/AndroidManifest.xml
@@ -14,4 +14,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<manifest package="androidx.compose.ui.viewbinding.samples" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.compose.ui.viewbinding.samples">
+ <application>
+ <activity android:name="androidx.compose.ui.samples.InflatedFragmentActivity"/>
+ </application>
+</manifest>
diff --git a/compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/FragmentRecreateTest.kt b/compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/FragmentRecreateTest.kt
new file mode 100644
index 0000000..66d57a99
--- /dev/null
+++ b/compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/FragmentRecreateTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.samples
+
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.compose.ui.viewbinding.samples.R
+import androidx.compose.ui.viewbinding.samples.databinding.TestFragmentLayoutBinding
+import androidx.compose.ui.viewinterop.AndroidViewBinding
+import androidx.fragment.app.FragmentActivity
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class FragmentRecreateTest {
+
+ @Test
+ fun testRecreateFragment() {
+ with(ActivityScenario.launch(InflatedFragmentActivity::class.java)) {
+ val fragment = withActivity {
+ supportFragmentManager.findFragmentById(R.id.fragment_container)!!
+ }
+ assertThat(fragment.requireView().parent).isNotNull()
+
+ recreate()
+
+ val recreatedFragment = withActivity {
+ supportFragmentManager.findFragmentById(R.id.fragment_container)!!
+ }
+ assertThat(recreatedFragment.requireView().parent).isNotNull()
+ }
+ }
+}
+
+class InflatedFragmentActivity : FragmentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ AndroidViewBinding(TestFragmentLayoutBinding::inflate)
+ }
+ }
+}
\ No newline at end of file
diff --git a/compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/InflatedFragment.kt b/compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/InflatedFragment.kt
new file mode 100644
index 0000000..e94e7fc
--- /dev/null
+++ b/compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/InflatedFragment.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.samples
+
+import androidx.compose.ui.viewbinding.samples.R
+import androidx.fragment.app.Fragment
+
+class InflatedFragment : Fragment(R.layout.sample_layout)
diff --git a/compose/ui/ui-viewbinding/samples/src/main/res/layout/test_fragment_layout.xml b/compose/ui/ui-viewbinding/samples/src/main/res/layout/test_fragment_layout.xml
new file mode 100644
index 0000000..0806f66
--- /dev/null
+++ b/compose/ui/ui-viewbinding/samples/src/main/res/layout/test_fragment_layout.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<androidx.fragment.app.FragmentContainerView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:name="androidx.compose.ui.samples.InflatedFragment"/>
\ No newline at end of file