Skip to content

Commit c607e03

Browse files
committed
Fix multi-child ViewRenderer NPE when removing Android Views on Activity cleanup.
With features such as a backstack that may render multiple children under a parent view, we are seeing crashes like this on activity destruction: ``` java.lang.RuntimeException: Unable to destroy activity {software.amazon.app.platform.demo/software.amazon.app.platform.recipes.FeatureActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.dispatchDetachedFromWindow()' on a null object reference at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:6269) at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:6301) at android.app.servertransaction.DestroyActivityItem.execute(DestroyActivityItem.java:52) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:63) at android.app.servertransaction.TransactionExecutor.executeLifecycleItem(TransactionExecutor.java:169) at android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:101) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:80) ``` This happens in any instance where there are multiple child views under a parent ViewGroup, and the hosting Activity is destroyed. We manually remove children from the parent, but this mutates the child sequence within the parent and results in an NPE when Android tries to do cleanup on its end. Adjust the child view removal logic to run on the main thread sequentially after any cleanup Android does.
1 parent d787ad9 commit c607e03

File tree

1 file changed

+9
-3
lines changed
  • renderer-android-view/public/src/androidMain/kotlin/software/amazon/app/platform/renderer

1 file changed

+9
-3
lines changed

renderer-android-view/public/src/androidMain/kotlin/software/amazon/app/platform/renderer/ViewRenderer.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package software.amazon.app.platform.renderer
33
import android.app.Activity
44
import android.app.Application
55
import android.os.Bundle
6+
import android.os.Handler
7+
import android.os.Looper
68
import android.view.LayoutInflater
79
import android.view.View
810
import android.view.ViewGroup
@@ -145,9 +147,13 @@ public abstract class ViewRenderer<in ModelT : BaseModel> : BaseAndroidViewRende
145147
lastModel = null
146148

147149
// Remove the view from the parent. In case the Renderer is reused we inflate a new
148-
// View and add it to the parent.
149-
if (view.parent === parent) {
150-
parent.removeView(view)
150+
// View and add it to the parent. This action must run after all currently queued main
151+
// thread operations finish. This is needed because we cannot remove views from parents in
152+
// the onDetach callback as this may lead to inconsistent view state and trigger crashes.
153+
Handler(Looper.getMainLooper()).post {
154+
if (view.parent === parent) {
155+
parent.removeView(view)
156+
}
151157
}
152158
}
153159

0 commit comments

Comments
 (0)