diff --git a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java index a324b5fd0..f2627f0ec 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java @@ -140,7 +140,7 @@ public final class ContentActivity extends StageActivity super.onCreate(savedInstanceState); setContentView(R.layout.activity_content); - SceneManager.getInstance().addSceneStateListener(mSceneStateListener); + addSceneStateListener(mSceneStateListener); mResources = getResources(); @@ -183,8 +183,9 @@ public final class ContentActivity extends StageActivity @Override protected void onDestroy() { + removeSceneStateListener(mSceneStateListener); + super.onDestroy(); - SceneManager.getInstance().removeSceneStateListener(mSceneStateListener); } @Override diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index 78f37a3f8..7c2f46e1a 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -54,6 +54,8 @@ public abstract class Scene { static final int SCENE_STATE_PAUSE = 7; static final int SCENE_STATE_REBIRTH = 8; + SceneManager mSceneManager; + private @Nullable Curtain mCurtain; private @Nullable Announcer mAnnouncer; @@ -65,18 +67,13 @@ public abstract class Scene { private int mState = SCENE_STATE_INIT; - protected static SceneManager sSceneManager; - private int mId; private boolean mHide; - static void setSceneManager(SceneManager sceneManager) { - sSceneManager = sceneManager; - } - - public Scene() { - mId = sSceneManager.nextId(); + public void setSceneManager(SceneManager sceneManager) { + mSceneManager = sceneManager; + mId = sceneManager.nextId(); } int getId() { @@ -101,7 +98,7 @@ public abstract class Scene { // If there is no StageActivity for SceneManager, yout will get AssertError public @NonNull StageActivity getStageActivity() { - StageActivity stageActivity = sSceneManager.getStageActivity(); + StageActivity stageActivity = mSceneManager.getStageActivity(); AssertUtils.assertNotNull("StageActivity is null", stageActivity); return stageActivity; } @@ -123,16 +120,16 @@ public abstract class Scene { } public void startScene(@NonNull Class sceneClass) { - sSceneManager.startScene(sceneClass, null, null); + mSceneManager.startScene(sceneClass, null, null); } public void startScene(@NonNull Class sceneClass, @Nullable Announcer announcer) { - sSceneManager.startScene(sceneClass, announcer, null); + mSceneManager.startScene(sceneClass, announcer, null); } public void startScene(@NonNull Class sceneClass, @Nullable Announcer announcer, @Nullable Curtain curtain) { - sSceneManager.startScene(sceneClass, announcer, curtain); + mSceneManager.startScene(sceneClass, announcer, curtain); } int getState() { @@ -148,7 +145,7 @@ public abstract class Scene { } public final void finish() { - sSceneManager.finishScene(this); + mSceneManager.finishScene(this); } void setHide(boolean hide) { @@ -422,7 +419,7 @@ public abstract class Scene { } void onBackPressedInternal() { - if (!endCurtainAnimation() && !sSceneManager.endLegacyScene()) { + if (!endCurtainAnimation() && !mSceneManager.endLegacyScene()) { onBackPressed(); } } @@ -448,11 +445,11 @@ public abstract class Scene { } void openFinished() { - sSceneManager.openScene(this); + mSceneManager.openScene(this); } void closeFinished() { - sSceneManager.closeScene(this); + mSceneManager.closeScene(this); } // It is constant diff --git a/app/src/main/java/com/hippo/scene/SceneApplication.java b/app/src/main/java/com/hippo/scene/SceneApplication.java index c30c7e025..b280b80b4 100644 --- a/app/src/main/java/com/hippo/scene/SceneApplication.java +++ b/app/src/main/java/com/hippo/scene/SceneApplication.java @@ -18,13 +18,18 @@ package com.hippo.scene; import android.app.Application; import android.content.Context; +import android.util.SparseArray; +import com.hippo.util.IntIdGenerator; +import com.hippo.util.Log; import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.RefWatcher; public class SceneApplication extends Application { + private static final String TAG = SceneApplication.class.getSimpleName(); - private SceneManager mSceneManager; + private SparseArray mSceneManagers; + private IntIdGenerator mIdGenerator; private RefWatcher mRefWatcher; @@ -32,15 +37,45 @@ public class SceneApplication extends Application { public void onCreate() { super.onCreate(); - mRefWatcher = LeakCanary.install(this); + mSceneManagers = new SparseArray<>(); + mIdGenerator = IntIdGenerator.create(); - mSceneManager = SceneManager.getInstance(); - StageActivity.setSceneManager(mSceneManager); - Scene.setSceneManager(mSceneManager); + mRefWatcher = LeakCanary.install(this); } - public SceneManager getSceneManager() { - return mSceneManager; + private SceneManager createSceneManager() { + int id = mIdGenerator.nextId(); + SceneManager sceneManager = new SceneManager(id); + mSceneManagers.put(id, sceneManager); + return sceneManager; + } + + private SceneManager getSceneManager(int id) { + SceneManager sceneManager = mSceneManagers.get(id); + if (sceneManager == null) { + Log.e(TAG, "Can't get SceneManager by id " + id); + sceneManager = new SceneManager(id); + } + return sceneManager; + } + + private void removeSceneManager(SceneManager sceneManager) { + mSceneManagers.remove(sceneManager.getId()); + } + + static SceneManager createSceneManager(Context context) { + SceneApplication application = (SceneApplication) context.getApplicationContext(); + return application.createSceneManager(); + } + + static SceneManager getSceneManager(Context context, int id) { + SceneApplication application = (SceneApplication) context.getApplicationContext(); + return application.getSceneManager(id); + } + + static void removeSceneManager(Context context, SceneManager sceneManager) { + SceneApplication application = (SceneApplication) context.getApplicationContext(); + application.removeSceneManager(sceneManager); } public static RefWatcher getRefWatcher(Context context) { diff --git a/app/src/main/java/com/hippo/scene/SceneDialog.java b/app/src/main/java/com/hippo/scene/SceneDialog.java index fca630282..d514506ae 100644 --- a/app/src/main/java/com/hippo/scene/SceneDialog.java +++ b/app/src/main/java/com/hippo/scene/SceneDialog.java @@ -25,6 +25,6 @@ public abstract class SceneDialog extends Scene { } public void show(@Nullable Curtain curtain) { - sSceneManager.showDialog(this, curtain); + mSceneManager.showDialog(this, curtain); } } diff --git a/app/src/main/java/com/hippo/scene/SceneManager.java b/app/src/main/java/com/hippo/scene/SceneManager.java index 1fdeda77e..baa1e88dd 100644 --- a/app/src/main/java/com/hippo/scene/SceneManager.java +++ b/app/src/main/java/com/hippo/scene/SceneManager.java @@ -35,6 +35,8 @@ public class SceneManager { private static final String TAG = SceneManager.class.getSimpleName(); + private int mId; + private Stack mSceneStack = new Stack<>(); private StageActivity mStageActivity; @@ -46,17 +48,12 @@ public class SceneManager { private List mSceneStateListenerList = new ArrayList<>(); - private static SceneManager sSceneManger; - - public static SceneManager getInstance() { - if (sSceneManger == null) { - sSceneManger = new SceneManager(); - } - return sSceneManger; + SceneManager(int id) { + mId = id; } - // Should only be called by SceneApplication - private SceneManager() { + int getId() { + return mId; } int nextId() { @@ -157,6 +154,7 @@ public class SceneManager { } Scene scene = createSceneByClass(sceneClass); + scene.setSceneManager(this); scene.setAnnouncer(announcer); scene.setCurtain(curtain); @@ -345,6 +343,10 @@ public class SceneManager { return mSceneStack; } + int getSceneSize() { + return mSceneStack.size(); + } + protected void onSaveInstanceState(Bundle outState) { for (Scene scene : mSceneStack) { scene.saveInstanceState(outState); diff --git a/app/src/main/java/com/hippo/scene/StageActivity.java b/app/src/main/java/com/hippo/scene/StageActivity.java index 9489b2e41..70d5c183d 100644 --- a/app/src/main/java/com/hippo/scene/StageActivity.java +++ b/app/src/main/java/com/hippo/scene/StageActivity.java @@ -25,35 +25,55 @@ import android.view.View; import com.hippo.app.StatsActivity; import com.hippo.util.IntIdGenerator; +import com.hippo.util.Log; public abstract class StageActivity extends StatsActivity { + private static final String TAG = StageActivity.class.getSimpleName(); + + private static final String KEY_SCENEN_MANAGER_ID = "scene_manager_id"; + private IntIdGenerator mActivityResultIdGenerator = IntIdGenerator.create(); private SparseArray mActivityResultListenerMap = new SparseArray<>(); - private static SceneManager sSceneManager; + private SceneManager mSceneManager; private int mFitPaddingBottom; - static void setSceneManager(SceneManager sceneManager) { - sSceneManager = sceneManager; - } - public abstract @NonNull StageLayout getStageLayout(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - ((SceneApplication) getApplication()).getSceneManager().setStageActivity(this); + if (savedInstanceState == null) { + // The first + mSceneManager = SceneApplication.createSceneManager(this); + } else { + int id = savedInstanceState.getInt(KEY_SCENEN_MANAGER_ID, -1); + if (id == -1) { + Log.e(TAG, "Can't get KEY_SCENEN_MANAGER_ID"); + mSceneManager = SceneApplication.createSceneManager(this); + } else { + mSceneManager = SceneApplication.getSceneManager(this, id); + } + } + + mSceneManager.setStageActivity(this); } @Override protected void onDestroy() { super.onDestroy(); - ((SceneApplication) getApplication()).getSceneManager().setStageActivity(null); + if (mSceneManager.getSceneSize() == 0) { + // Remove this SceneManager + SceneApplication.removeSceneManager(this, mSceneManager); + } + + mSceneManager.setStageActivity(null); + mSceneManager = null; } public int getFitPaddingBottom() { @@ -63,7 +83,7 @@ public abstract class StageActivity extends StatsActivity { public void setFitPaddingBottom(int b) { if (mFitPaddingBottom != b) { mFitPaddingBottom = b; - for (Scene scene : sSceneManager.getSceneStack()) { + for (Scene scene : mSceneManager.getSceneStack()) { scene.setFitPaddingBottom(b); } } @@ -80,16 +100,16 @@ public abstract class StageActivity extends StatsActivity { } public void startScene(@NonNull Class sceneClass) { - sSceneManager.startScene(sceneClass, null, null); + mSceneManager.startScene(sceneClass, null, null); } public void startScene(@NonNull Class sceneClass, @Nullable Announcer announcer) { - sSceneManager.startScene(sceneClass, announcer, null); + mSceneManager.startScene(sceneClass, announcer, null); } public void startScene(@NonNull Class sceneClass, @Nullable Announcer announcer, @Nullable Curtain curtain) { - sSceneManager.startScene(sceneClass, announcer, curtain); + mSceneManager.startScene(sceneClass, announcer, curtain); } /** @@ -106,6 +126,27 @@ public abstract class StageActivity extends StatsActivity { return id; } + public void addSceneStateListener(SceneManager.SceneStateListener listener) { + mSceneManager.addSceneStateListener(listener); + } + + public void removeSceneStateListener(SceneManager.SceneStateListener listener) { + mSceneManager.removeSceneStateListener(listener); + } + + /** + * {@inheritDoc} + *

+ * Only work when there is no scene in the stage + *

+ */ + @Override + public void finish() { + if (mSceneManager.getSceneSize() == 0) { + super.finish(); + } + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); @@ -119,7 +160,7 @@ public abstract class StageActivity extends StatsActivity { @Override public void onBackPressed() { - if (!sSceneManager.onBackPressed()) { + if (!mSceneManager.onBackPressed()) { super.onBackPressed(); } } @@ -128,13 +169,15 @@ public abstract class StageActivity extends StatsActivity { protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - sSceneManager.onSaveInstanceState(outState); + mSceneManager.onSaveInstanceState(outState); + + outState.putInt(KEY_SCENEN_MANAGER_ID, mSceneManager.getId()); } @Override protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); - sSceneManager.onRestoreInstanceState(savedInstanceState); + mSceneManager.onRestoreInstanceState(savedInstanceState); } }