androidbroadcast / ViewBindingPropertyDelegate

Make work with Android View Binding simpler
https://proandroiddev.com/make-android-view-binding-great-with-kotlin-b71dd9c87719
Apache License 2.0
1.42k stars 102 forks source link

Access to viewBinding after Lifecycle is destroyed or hasn't created yet. The instance of viewBinding will be not cached. #98

Closed Reginer closed 2 years ago

Reginer commented 2 years ago

version  1.5.6

 at by.kirich1409.viewbindingdelegate.LifecycleViewBindingProperty.runStrictModeChecks(ViewBindingProperty.kt:112)

` ``
Don't  throw exception , OK ?
kirich1409 commented 2 years ago

@Reginer , I need a sample where the issue is reproducible

Reginer commented 2 years ago

After activity destroy ,binding.textView.setText

kirich1409 commented 2 years ago

I've checked the behavior and it's normal. After Lifecycle became DESTROYED viewbinding keep last creataed version.

Reginer commented 2 years ago

May be it's normal you've checked , But app creash . Why throw an exception? shouldn't do anything.

Reginer commented 2 years ago

https://github.com/androidbroadcast/ViewBindingPropertyDelegate/blob/d810b0b446edd3e2489f9a6ba7bab456b7a26602/vbpd/vbpd-noreflection/src/main/java/by/kirich1409/viewbindingdelegate/ViewBindingProperty.kt#L112

image

Reginer commented 2 years ago

Oh , strictMode default value should be false.

kirich1409 commented 2 years ago

It's not connected with StrictMode. It's part of normal flow now to work with ViewBinding when view isn't exist

cdongieux commented 2 years ago

Hi @kirich1409

I have the same problem in my app:

class HomeActivity : FragmentActivity() {
    private val binding: ActivityHomeBinding by viewBinding()

    override fun onDestroy() {
        binding.list.adapter = null     // crash happens here
        super.onDestroy()
    }
}

With list being a RecyclerView.

And the stacktrace:

Caused by java.lang.IllegalStateException: Access to viewBinding after Lifecycle is destroyed or hasn't created yet. The instance of viewBinding will be not cached.
       at by.kirich1409.viewbindingdelegate.LifecycleViewBindingProperty.runStrictModeChecks(ViewBindingProperty.kt:112)
       at by.kirich1409.viewbindingdelegate.LifecycleViewBindingProperty.getValue(ViewBindingProperty.kt:91)
       at by.kirich1409.viewbindingdelegate.LifecycleViewBindingProperty.getValue(ViewBindingProperty.kt:71)
       at net.foobar.ui.home.HomeActivity.getBinding(HomeActivity.kt:31)
       at net.foobar.ui.home.HomeActivity.onDestroy(HomeActivity.kt:174)
       at android.app.Activity.performDestroy(Activity.java:8063)
       at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1341)
       at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4926)
       at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4970)
       at android.app.servertransaction.DestroyActivityItem.execute(DestroyActivityItem.java:44)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
       at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:7356)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

As the documentation in Lifecycle.State.DESTROYED says:

this state is reached right before Activity's onDestroy call.

So technically the Activity is not destroyed yet, and its views neither. So I think the runStrictModeChecks() in ViewBindingProperty.getValue() is wrong.

What do you think about it?

kirich1409 commented 2 years ago

@cdongieux , sadly, but it can be normal. Destroy in the VИЗВ associated with Lifecycle, not with Activity lifecycle callbacks. It's better to use

private val binding: ActivityHomeBinding by viewBinding(onViewDestroyed = {...})
Reginer commented 2 years ago

add ViewBindingPropertyDelegate.strictMode = false in Application#onCreate

Maybe the author forgot what he wrote .