Skip to content

Commit 5e70e87

Browse files
committed
JmeSurfaceView: corrected the dispatching algorithm of SystemListener#destroy
1 parent 8ba6574 commit 5e70e87

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

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

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import android.opengl.GLSurfaceView;
4343
import android.os.Handler;
4444
import android.util.AttributeSet;
45+
import android.view.View;
4546
import android.widget.RelativeLayout;
4647
import android.widget.Toast;
4748
import androidx.annotation.NonNull;
@@ -239,11 +240,7 @@ public void startRenderer(int delayMillis) {
239240
}
240241

241242
private void removeGLSurfaceView() {
242-
((Activity) getContext()).runOnUiThread(() -> {
243-
if (glSurfaceView != null) {
244-
JmeSurfaceView.this.removeView(glSurfaceView);
245-
}
246-
});
243+
((Activity) getContext()).runOnUiThread(() -> JmeSurfaceView.this.removeView(glSurfaceView));
247244
}
248245

249246
@Override
@@ -265,19 +262,34 @@ public void handleError(String errorMsg, Throwable throwable) {
265262
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
266263
switch (event) {
267264
case ON_DESTROY:
268-
/*destroy only if the policy flag is enabled*/
269-
if (destructionPolicy == DestructionPolicy.DESTROY_WHEN_FINISH) {
270-
legacyApplication.stop(!isGLThreadPaused());
271-
}
265+
// activity is off the foreground stack
266+
// activity is being destructed completely as a result of Activity#finish()
267+
// this is a killable automata state!
268+
jmeSurfaceViewLogger.log(Level.INFO, "Hosting Activity has been destructed.");
272269
break;
273270
case ON_PAUSE:
274-
loseFocus();
271+
// activity is still on the foreground stack but not
272+
// on the topmost level or before transition to stopped/hidden or destroyed state
273+
// as a result of dispatch to Activity#finish()
274+
// activity is no longer visible and is out of foreground
275+
if (((Activity) getContext()).isFinishing()) {
276+
if (destructionPolicy == DestructionPolicy.DESTROY_WHEN_FINISH) {
277+
legacyApplication.stop(!isGLThreadPaused());
278+
} else if (destructionPolicy == DestructionPolicy.KEEP_WHEN_FINISH) {
279+
jmeSurfaceViewLogger.log(Level.INFO, "Context stops, but game is still running.");
280+
}
281+
} else {
282+
loseFocus();
283+
}
275284
break;
276285
case ON_RESUME:
286+
// activity is back to the topmost of the
287+
// foreground stack
277288
gainFocus();
278289
break;
279290
case ON_STOP:
280-
jmeSurfaceViewLogger.log(Level.INFO, "Context stops, but game is still running");
291+
// activity is out off the foreground stack or being destructed by a finishing dispatch
292+
// this is a killable automata state!
281293
break;
282294
}
283295
}
@@ -405,11 +417,12 @@ public void loseFocus() {
405417
@Override
406418
public void destroy() {
407419
/*skip the destroy block if the invoking instance is null*/
408-
if (legacyApplication == null) {
409-
return;
420+
if (glSurfaceView != null) {
421+
removeGLSurfaceView();
422+
}
423+
if (legacyApplication != null) {
424+
legacyApplication.destroy();
410425
}
411-
removeGLSurfaceView();
412-
legacyApplication.destroy();
413426
/*help the Dalvik Garbage collector to destruct the pointers, by making them nullptr*/
414427
/*context instances*/
415428
legacyApplication = null;
@@ -430,10 +443,10 @@ public void destroy() {
430443
onRendererCompleted = null;
431444
onExceptionThrown = null;
432445
onLayoutDrawn = null;
433-
/*nullifying the static memory (pushing zero to registers to prepare for a clean use)*/
434446
GameState.setLegacyApplication(null);
435447
GameState.setFirstUpdatePassed(false);
436-
jmeSurfaceViewLogger.log(Level.INFO, "Context and Game have been destructed");
448+
JmeAndroidSystem.setView(null);
449+
jmeSurfaceViewLogger.log(Level.INFO, "Context and Game have been destructed.");
437450
}
438451

439452
@Override
@@ -516,11 +529,13 @@ public void bindAppStateToActivityLifeCycle(final boolean condition) {
516529
/*register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
517530
if (getContext() instanceof LifecycleOwner) {
518531
((LifecycleOwner) getContext()).getLifecycle().addObserver(JmeSurfaceView.this);
532+
jmeSurfaceViewLogger.log(Level.INFO, "Command binding SurfaceView to the Activity Lifecycle.");
519533
}
520534
} else {
521535
/*un-register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
522536
if (getContext() instanceof LifecycleOwner) {
523537
((LifecycleOwner) getContext()).getLifecycle().removeObserver(JmeSurfaceView.this);
538+
jmeSurfaceViewLogger.log(Level.INFO, "Command removing SurfaceView from the Activity Lifecycle.");
524539
}
525540
}
526541
}
@@ -917,7 +932,7 @@ public void setShowErrorDialog(boolean showErrorDialog) {
917932
}
918933

919934
/**
920-
* Determines whether the app context would be destructed
935+
* Determines whether the app context would be destructed as a result of dispatching {@link Activity#finish()}
921936
* with the holder activity context in case of {@link DestructionPolicy#DESTROY_WHEN_FINISH} or be
922937
* spared for a second use in case of {@link DestructionPolicy#KEEP_WHEN_FINISH}.
923938
* Default value is : {@link DestructionPolicy#DESTROY_WHEN_FINISH}.
@@ -926,12 +941,14 @@ public void setShowErrorDialog(boolean showErrorDialog) {
926941
*/
927942
public enum DestructionPolicy {
928943
/**
929-
* Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication}).
944+
* Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication})
945+
* as a result of dispatching {@link Activity#finish()}.
930946
*/
931947
DESTROY_WHEN_FINISH,
932948
/**
933949
* 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.
950+
* when the activity context is destroyed dispatching {@link Activity#finish()}, but the {@link android.app.Application}
951+
* stills in the background.
935952
*/
936953
KEEP_WHEN_FINISH
937954
}

0 commit comments

Comments
 (0)