11/*
2- * Copyright (c) 2009-2022 jMonkeyEngine
2+ * Copyright (c) 2009-2025 jMonkeyEngine
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
@@ -239,11 +239,7 @@ public void startRenderer(int delayMillis) {
239239 }
240240
241241 private void removeGLSurfaceView () {
242- ((Activity ) getContext ()).runOnUiThread (() -> {
243- if (glSurfaceView != null ) {
244- JmeSurfaceView .this .removeView (glSurfaceView );
245- }
246- });
242+ ((Activity ) getContext ()).runOnUiThread (() -> JmeSurfaceView .this .removeView (glSurfaceView ));
247243 }
248244
249245 @ Override
@@ -265,19 +261,34 @@ public void handleError(String errorMsg, Throwable throwable) {
265261 public void onStateChanged (@ NonNull LifecycleOwner source , @ NonNull Lifecycle .Event event ) {
266262 switch (event ) {
267263 case ON_DESTROY :
268- /*destroy only if the policy flag is enabled*/
269- if ( destructionPolicy == DestructionPolicy . DESTROY_WHEN_FINISH ) {
270- legacyApplication . stop (! isGLThreadPaused ());
271- }
264+ // activity is off the foreground stack
265+ // activity is being destructed completely as a result of Activity#finish()
266+ // this is a killable automata state!
267+ jmeSurfaceViewLogger . log ( Level . INFO , "Hosting Activity has been destructed." );
272268 break ;
273269 case ON_PAUSE :
274- loseFocus ();
270+ // activity is still on the foreground stack but not
271+ // on the topmost level or before transition to stopped/hidden or destroyed state
272+ // as a result of dispatch to Activity#finish()
273+ // activity is no longer visible and is out of foreground
274+ if (((Activity ) getContext ()).isFinishing ()) {
275+ if (destructionPolicy == DestructionPolicy .DESTROY_WHEN_FINISH ) {
276+ legacyApplication .stop (!isGLThreadPaused ());
277+ } else if (destructionPolicy == DestructionPolicy .KEEP_WHEN_FINISH ) {
278+ jmeSurfaceViewLogger .log (Level .INFO , "Context stops, but game is still running." );
279+ }
280+ } else {
281+ loseFocus ();
282+ }
275283 break ;
276284 case ON_RESUME :
285+ // activity is back to the topmost of the
286+ // foreground stack
277287 gainFocus ();
278288 break ;
279289 case ON_STOP :
280- jmeSurfaceViewLogger .log (Level .INFO , "Context stops, but game is still running" );
290+ // activity is out off the foreground stack or being destructed by a finishing dispatch
291+ // this is a killable automata state!
281292 break ;
282293 }
283294 }
@@ -404,13 +415,13 @@ public void loseFocus() {
404415
405416 @ Override
406417 public void destroy () {
407- /*skip the destroy block if the invoking instance is null*/
408- if (legacyApplication == null ) {
409- return ;
418+ if (glSurfaceView != null ) {
419+ removeGLSurfaceView ();
420+ }
421+ if (legacyApplication != null ) {
422+ legacyApplication .destroy ();
410423 }
411- removeGLSurfaceView ();
412- legacyApplication .destroy ();
413- /*help the Dalvik Garbage collector to destruct the pointers, by making them nullptr*/
424+ /*help the Dalvik Garbage collector to destruct the objects, by releasing their references*/
414425 /*context instances*/
415426 legacyApplication = null ;
416427 appSettings = null ;
@@ -430,10 +441,10 @@ public void destroy() {
430441 onRendererCompleted = null ;
431442 onExceptionThrown = null ;
432443 onLayoutDrawn = null ;
433- /*nullifying the static memory (pushing zero to registers to prepare for a clean use)*/
434444 GameState .setLegacyApplication (null );
435445 GameState .setFirstUpdatePassed (false );
436- jmeSurfaceViewLogger .log (Level .INFO , "Context and Game have been destructed" );
446+ JmeAndroidSystem .setView (null );
447+ jmeSurfaceViewLogger .log (Level .INFO , "Context and Game have been destructed." );
437448 }
438449
439450 @ Override
@@ -516,11 +527,13 @@ public void bindAppStateToActivityLifeCycle(final boolean condition) {
516527 /*register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
517528 if (getContext () instanceof LifecycleOwner ) {
518529 ((LifecycleOwner ) getContext ()).getLifecycle ().addObserver (JmeSurfaceView .this );
530+ jmeSurfaceViewLogger .log (Level .INFO , "Command binding SurfaceView to the Activity Lifecycle." );
519531 }
520532 } else {
521533 /*un-register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
522534 if (getContext () instanceof LifecycleOwner ) {
523535 ((LifecycleOwner ) getContext ()).getLifecycle ().removeObserver (JmeSurfaceView .this );
536+ jmeSurfaceViewLogger .log (Level .INFO , "Command removing SurfaceView from the Activity Lifecycle." );
524537 }
525538 }
526539 }
@@ -917,7 +930,7 @@ public void setShowErrorDialog(boolean showErrorDialog) {
917930 }
918931
919932 /**
920- * Determines whether the app context would be destructed
933+ * Determines whether the app context would be destructed as a result of dispatching {@link Activity#finish()}
921934 * with the holder activity context in case of {@link DestructionPolicy#DESTROY_WHEN_FINISH} or be
922935 * spared for a second use in case of {@link DestructionPolicy#KEEP_WHEN_FINISH}.
923936 * Default value is : {@link DestructionPolicy#DESTROY_WHEN_FINISH}.
@@ -926,12 +939,14 @@ public void setShowErrorDialog(boolean showErrorDialog) {
926939 */
927940 public enum DestructionPolicy {
928941 /**
929- * Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication}).
942+ * Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication})
943+ * as a result of dispatching {@link Activity#finish()}.
930944 */
931945 DESTROY_WHEN_FINISH ,
932946 /**
933947 * Spares the game context inside a static memory {@link GameState#legacyApplication}
934- * when the activity context is destroyed, but the app stills in the background.
948+ * when the activity context is destroyed dispatching {@link Activity#finish()}, but the {@link android.app.Application}
949+ * stills in the background.
935950 */
936951 KEEP_WHEN_FINISH
937952 }
0 commit comments