Pārlūkot izejas kodu

JmeSurfaceView: corrected the dispatching algorithm of SystemListener#destroy

pavl_g 7 mēneši atpakaļ
vecāks
revīzija
5e70e87987

+ 37 - 20
jme3-android/src/main/java/com/jme3/view/surfaceview/JmeSurfaceView.java

@@ -42,6 +42,7 @@ import android.content.pm.ConfigurationInfo;
 import android.opengl.GLSurfaceView;
 import android.os.Handler;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.RelativeLayout;
 import android.widget.Toast;
 import androidx.annotation.NonNull;
@@ -239,11 +240,7 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener, Di
     }
 
     private void removeGLSurfaceView() {
-        ((Activity) getContext()).runOnUiThread(() -> {
-            if (glSurfaceView != null) {
-                JmeSurfaceView.this.removeView(glSurfaceView);
-            }
-        });
+        ((Activity) getContext()).runOnUiThread(() -> JmeSurfaceView.this.removeView(glSurfaceView));
     }
 
     @Override
@@ -265,19 +262,34 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener, Di
     public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
         switch (event) {
             case ON_DESTROY:
-                /*destroy only if the policy flag is enabled*/
-                if (destructionPolicy == DestructionPolicy.DESTROY_WHEN_FINISH) {
-                    legacyApplication.stop(!isGLThreadPaused());
-                }
+                // activity is off the foreground stack
+                // activity is being destructed completely as a result of Activity#finish()
+                // this is a killable automata state!
+                jmeSurfaceViewLogger.log(Level.INFO, "Hosting Activity has been destructed.");
                 break;
             case ON_PAUSE:
-                loseFocus();
+                // activity is still on the foreground stack but not
+                // on the topmost level or before transition to stopped/hidden or destroyed state
+                // as a result of dispatch to Activity#finish()
+                // activity is no longer visible and is out of foreground
+                if (((Activity) getContext()).isFinishing()) {
+                    if (destructionPolicy == DestructionPolicy.DESTROY_WHEN_FINISH) {
+                        legacyApplication.stop(!isGLThreadPaused());
+                    } else if (destructionPolicy == DestructionPolicy.KEEP_WHEN_FINISH) {
+                        jmeSurfaceViewLogger.log(Level.INFO, "Context stops, but game is still running.");
+                    }
+                } else {
+                    loseFocus();
+                }
                 break;
             case ON_RESUME:
+                // activity is back to the topmost of the
+                // foreground stack
                 gainFocus();
                 break;
             case ON_STOP:
-                jmeSurfaceViewLogger.log(Level.INFO, "Context stops, but game is still running");
+                // activity is out off the foreground stack or being destructed by a finishing dispatch
+                // this is a killable automata state!
                 break;
         }
     }
@@ -405,11 +417,12 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener, Di
     @Override
     public void destroy() {
         /*skip the destroy block if the invoking instance is null*/
-        if (legacyApplication == null) {
-            return;
+        if (glSurfaceView != null) {
+            removeGLSurfaceView();
+        }
+        if (legacyApplication != null) {
+            legacyApplication.destroy();
         }
-        removeGLSurfaceView();
-        legacyApplication.destroy();
         /*help the Dalvik Garbage collector to destruct the pointers, by making them nullptr*/
         /*context instances*/
         legacyApplication = null;
@@ -430,10 +443,10 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener, Di
         onRendererCompleted = null;
         onExceptionThrown = null;
         onLayoutDrawn = null;
-        /*nullifying the static memory (pushing zero to registers to prepare for a clean use)*/
         GameState.setLegacyApplication(null);
         GameState.setFirstUpdatePassed(false);
-        jmeSurfaceViewLogger.log(Level.INFO, "Context and Game have been destructed");
+        JmeAndroidSystem.setView(null);
+        jmeSurfaceViewLogger.log(Level.INFO, "Context and Game have been destructed.");
     }
 
     @Override
@@ -516,11 +529,13 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener, Di
             /*register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
             if (getContext() instanceof LifecycleOwner) {
                 ((LifecycleOwner) getContext()).getLifecycle().addObserver(JmeSurfaceView.this);
+                jmeSurfaceViewLogger.log(Level.INFO, "Command binding SurfaceView to the Activity Lifecycle.");
             }
         } else {
             /*un-register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
             if (getContext() instanceof LifecycleOwner) {
                 ((LifecycleOwner) getContext()).getLifecycle().removeObserver(JmeSurfaceView.this);
+                jmeSurfaceViewLogger.log(Level.INFO, "Command removing SurfaceView from the Activity Lifecycle.");
             }
         }
     }
@@ -917,7 +932,7 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener, Di
     }
 
     /**
-     * Determines whether the app context would be destructed
+     * Determines whether the app context would be destructed as a result of dispatching {@link Activity#finish()}
      * with the holder activity context in case of {@link DestructionPolicy#DESTROY_WHEN_FINISH} or be
      * spared for a second use in case of {@link DestructionPolicy#KEEP_WHEN_FINISH}.
      * Default value is : {@link DestructionPolicy#DESTROY_WHEN_FINISH}.
@@ -926,12 +941,14 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener, Di
      */
     public enum DestructionPolicy {
         /**
-         * Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication}).
+         * Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication})
+         * as a result of dispatching {@link Activity#finish()}.
          */
         DESTROY_WHEN_FINISH,
         /**
          * Spares the game context inside a static memory {@link GameState#legacyApplication}
-         * when the activity context is destroyed, but the app stills in the background.
+         * when the activity context is destroyed dispatching {@link Activity#finish()}, but the {@link android.app.Application}
+         * stills in the background.
          */
         KEEP_WHEN_FINISH
     }