Skip to content

UninitializedPropertyAccessException happens if View is GONE #134

@cdongieux

Description

@cdongieux

Hi,

A UninitializedPropertyAccessException is raised during LifecycleOwner destruction (e.g. Activity finishes) when the button visibility is View.GONE.
An easy way to reproduce this issue is to set a CircularProgress*Button XML property android:visibility to gone, launch the Activity holding this button, and press the Back navigation button.

Stack trace:

2019-05-16 10:00:33.846 22258-22258/br.com.simplepass.loadingbutton E/AndroidRuntime: FATAL EXCEPTION: main
    Process: br.com.simplepass.loadingbutton, PID: 22258
    java.lang.RuntimeException: Unable to destroy activity {br.com.simplepass.loadingbutton/br.com.simplepass.loadingbuttonsample.MainActivity}: java.lang.RuntimeException: Failed to call observer method
        at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4458)
        at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4476)
        at android.app.servertransaction.DestroyActivityItem.execute(DestroyActivityItem.java:39)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.RuntimeException: Failed to call observer method
        at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:225)
        at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:193)
        at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:184)
        at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:36)
        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:355)
        at androidx.lifecycle.LifecycleRegistry.backwardPass(LifecycleRegistry.java:309)
        at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:328)
        at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:138)
        at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:124)
        at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:122)
        at androidx.lifecycle.ReportFragment.onDestroy(ReportFragment.java:107)
        at android.app.Fragment.performDestroy(Fragment.java:2782)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1451)
        at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1576)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1637)
        at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3046)
        at android.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:3026)
        at android.app.FragmentController.dispatchDestroy(FragmentController.java:248)
        at android.app.Activity.performDestroy(Activity.java:7394)
        at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1306)
        at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4443)
        at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4476) 
        at android.app.servertransaction.DestroyActivityItem.execute(DestroyActivityItem.java:39) 
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
     Caused by: kotlin.UninitializedPropertyAccessException: lateinit property initialState has not been initialized
        at br.com.simplepass.loadingbutton.customViews.CircularProgressButton.access$getInitialState$p(CircularProgressButton.kt:22)
        at br.com.simplepass.loadingbutton.customViews.CircularProgressButton$morphAnimator$2.invoke(CircularProgressButton.kt:72)
        at br.com.simplepass.loadingbutton.customViews.CircularProgressButton$morphAnimator$2.invoke(CircularProgressButton.kt:22)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at br.com.simplepass.loadingbutton.customViews.CircularProgressButton.getMorphAnimator(Unknown Source:7)
        at br.com.simplepass.loadingbutton.customViews.CircularProgressButton.dispose(CircularProgressButton.kt:173)

In your implementation the initialState var is lateinit, and it is only initialized in saveInitialState() which might not be called. Actually it is only called in the presenter's onDraw() method. In the use case I described above the onDraw() method is never called because the View visibility state is View.GONE.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions