From 029c786b2bd1b1d4e516b9a97453106a3369e9c7 Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Mon, 9 Mar 2026 18:35:55 +0300 Subject: [PATCH 1/2] chore: add .worktrees/ to .gitignore Co-Authored-By: Claude Opus 4.6 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 489e3d0..aae09fb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ .externalNativeBuild .cxx firebase-debug.log +.worktrees/ From 0619668b8bc15f8f4e27af7127491d0a98ddbc06 Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Mon, 9 Mar 2026 20:01:16 +0300 Subject: [PATCH 2/2] fix: correct @JvmName in ViewGroupBindings, fix nullable in findRootView, add tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix @JvmName("viewBindingFragment") → "viewBindingViewGroup"/"viewBindingViewGroupInflate" in reflection ViewGroupBindings (copy-paste error from FragmentViewBindings) - Fix DialogFragment.findRootView() using findViewById (nullable) instead of requireViewByIdCompat (non-null) when showsDialog=false - Add EagerViewBindingProperty.clear() test verifying no-op behavior - Add ActivityViewBindingProperty test verifying binding recreation after clear() Co-Authored-By: Claude Opus 4.6 --- .../vbpd/EagerViewBindingPropertyTest.kt | 11 ++++++ .../vbpd/ViewGroupBindings.kt | 8 ++--- .../vbpd/internal/VbpdUtils.kt | 2 +- .../vbpd/ActivityViewBindingPropertyTest.kt | 34 +++++++++++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/vbpd-core/src/test/kotlin/dev/androidbroadcast/vbpd/EagerViewBindingPropertyTest.kt b/vbpd-core/src/test/kotlin/dev/androidbroadcast/vbpd/EagerViewBindingPropertyTest.kt index bfda4a9..6c27941 100644 --- a/vbpd-core/src/test/kotlin/dev/androidbroadcast/vbpd/EagerViewBindingPropertyTest.kt +++ b/vbpd-core/src/test/kotlin/dev/androidbroadcast/vbpd/EagerViewBindingPropertyTest.kt @@ -40,4 +40,15 @@ class EagerViewBindingPropertyTest { val second = property.getValue(thisRef, mockProperty) assertEquals(first, second) } + + @Test + fun `clear does not affect getValue`() { + val binding = createMockBinding() + val property = EagerViewBindingProperty(binding) + val thisRef = Any() + + property.clear() + val result = property.getValue(thisRef, mockProperty) + assertEquals(binding, result) + } } diff --git a/vbpd-reflection/src/main/kotlin/dev/androidbroadcast/vbpd/ViewGroupBindings.kt b/vbpd-reflection/src/main/kotlin/dev/androidbroadcast/vbpd/ViewGroupBindings.kt index 6b2f8a9..fd428cb 100644 --- a/vbpd-reflection/src/main/kotlin/dev/androidbroadcast/vbpd/ViewGroupBindings.kt +++ b/vbpd-reflection/src/main/kotlin/dev/androidbroadcast/vbpd/ViewGroupBindings.kt @@ -14,7 +14,7 @@ import androidx.viewbinding.ViewBinding * * @return [ViewBindingProperty] that holds [ViewBinding] instance */ -@JvmName("viewBindingFragment") +@JvmName("viewBindingViewGroup") public inline fun ViewGroup.viewBinding( createMethod: CreateMethod = CreateMethod.BIND, ): ViewBindingProperty = viewBinding(T::class.java, createMethod) @@ -27,7 +27,7 @@ public inline fun ViewGroup.viewBinding( * * @return [ViewBindingProperty] that holds [ViewBinding] instance */ -@JvmName("viewBindingFragment") +@JvmName("viewBindingViewGroup") @JvmOverloads public fun ViewGroup.viewBinding( viewBindingClass: Class, @@ -50,7 +50,7 @@ public fun ViewGroup.viewBinding( * * @return [ViewBindingProperty] that holds [ViewBinding] instance */ -@JvmName("viewBindingFragment") +@JvmName("viewBindingViewGroupInflate") public inline fun ViewGroup.viewBinding(attachToRoot: Boolean = false): ViewBindingProperty = viewBinding(T::class.java, attachToRoot) @@ -62,7 +62,7 @@ public inline fun ViewGroup.viewBinding(attachToRoot: * * @return [ViewBindingProperty] that holds [ViewBinding] instance */ -@JvmName("viewBindingFragment") +@JvmName("viewBindingViewGroupInflate") public fun ViewGroup.viewBinding( viewBindingClass: Class, attachToRoot: Boolean = false, diff --git a/vbpd/src/main/kotlin/dev/androidbroadcast/vbpd/internal/VbpdUtils.kt b/vbpd/src/main/kotlin/dev/androidbroadcast/vbpd/internal/VbpdUtils.kt index e8c1562..44a25bd 100644 --- a/vbpd/src/main/kotlin/dev/androidbroadcast/vbpd/internal/VbpdUtils.kt +++ b/vbpd/src/main/kotlin/dev/androidbroadcast/vbpd/internal/VbpdUtils.kt @@ -52,7 +52,7 @@ public fun DialogFragment.findRootView( if (viewBindingRootId != 0) requireViewByIdCompat(viewBindingRootId) else this } } else { - return requireView().findViewById(viewBindingRootId) + return requireView().requireViewByIdCompat(viewBindingRootId) } } diff --git a/vbpd/src/test/kotlin/dev/androidbroadcast/vbpd/ActivityViewBindingPropertyTest.kt b/vbpd/src/test/kotlin/dev/androidbroadcast/vbpd/ActivityViewBindingPropertyTest.kt index 8984dfb..dfb96a8 100644 --- a/vbpd/src/test/kotlin/dev/androidbroadcast/vbpd/ActivityViewBindingPropertyTest.kt +++ b/vbpd/src/test/kotlin/dev/androidbroadcast/vbpd/ActivityViewBindingPropertyTest.kt @@ -11,6 +11,9 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner +import kotlin.reflect.KProperty +import kotlin.test.assertEquals +import kotlin.test.assertNotEquals import kotlin.test.assertNotNull @RunWith(RobolectricTestRunner::class) @@ -55,6 +58,37 @@ class ActivityViewBindingPropertyTest { val activity = controller.get() assertNotNull(activity.binding) + // Verify full lifecycle completes without crash + // onDestroy triggers clear() which nulls binding and unregisters callbacks controller.pause().stop().destroy() } + + @Test + fun `clear resets binding and allows recreation`() { + val mockProperty = mockk>(relaxed = true) + var callCount = 0 + val delegate = + ActivityViewBindingProperty { activity -> + callCount++ + mockk { + every { root } returns View(activity) + } + } + + val controller = + Robolectric + .buildActivity(TestActivity::class.java) + .create() + .start() + .resume() + val activity = controller.get() + + val binding1 = delegate.getValue(activity, mockProperty) + assertEquals(1, callCount) + + delegate.clear() + val binding2 = delegate.getValue(activity, mockProperty) + assertEquals(2, callCount) + assertNotEquals(binding1, binding2, "After clear(), a new binding should be created") + } }