当初市面上很多 app 上都有小游戏 (或叫 h5 游戏),它们借助小游戏来进步整个 app 的粘性。像微信 app、趣头条 app、哈啰 app 上曾经呈现了小游戏模块。
用户聊天、刷资讯、骑车之余能够关上小游戏劳动放松,如果忽然间来音讯了或者玩手游累了想看资讯,敞开游戏页面后,再次关上游戏是接着玩,不须要从新加载游戏。
如何实现这种成果呢?
咱们晓得 activity 敞开后,再次关上必定要走 onCreate 生命周期,那么页面相干资源就要重建,这样就得从新加载游戏了。
微信小游戏是如何做到,敞开 activity 后,再次关上会保留之前的资源和状态呢?
实际上,微信小游戏敞开 activity 关不是 finish 掉了,而且跳转到其它页面了,小游戏页面还在后盾运行,游戏也处于暂停状态,相干资源还在内存保留,没有被回收。再次关上同一个游戏,那么就不会再从新加载了。
那么这外面就波及两个问题。
第一个问题,从游戏页面返回上一个页面或者跳转到其它页面,如何保障指标页面不会重建呢?
这个很简略,把指标页面启动模式设置成 SingleTask 或者 SingleTop 就能够了:
<activity
android:name="com.devnn.demo.MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
或者在跳转的 Intent 上加上标记:clearTop 或者 singleTop 也能达到同样的成果:
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
clearTop 相似于 SingleTask,是革除指标 activity 之上的 activity 来保障指标 activity 不重建,这个实用于回到主页面。
SginleTop 是保障栈顶的 activity 惟一,这个实用于从一个栈跳转到另一个栈的栈顶页面。(请接着看第二个问题。)
第二个问题,再次回到游戏,如何保障游戏页面不会重建呢?
这个其实也波及到启动模式常识。将小游戏页面启动模式设置成 SingleInstance 即可。SingleInstance 示意,将 activity 存在在独自的 task 栈中。那么两个栈中的页面来回切换就不便自若了。配置如下:
<activity
android:name="com.devnn.demo.ActivityA"
android:launchMode="singleInstance">
</activity>
笔者做了一个 demo 实现了小游戏这种场景。其中 MainActivity 是主页面,ActivityA 是仿小游戏页面。
MainActivity.java
package com.devnn.demo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private String TAG="MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {Log.i(TAG,"onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {Log.i(TAG,"onResume");
super.onResume();}
@Override
protected void onNewIntent(Intent intent) {Log.i(TAG,"onNewIntent");
super.onNewIntent(intent);
}
public void toActivityA(View view) {Intent intent = new Intent(this, ActivityA.class);
startActivity(intent);
}
}
ActivityA.java
package com.devnn.demo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class ActivityA extends AppCompatActivity {
private String TAG = "ActivityA";
@Override
protected void onCreate(Bundle savedInstanceState) {Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
Log.i(TAG, "onCreate_task_id="+getTaskId());
}
@Override
public void onBackPressed() {Log.i(TAG, "onBackPressed");
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
// moveTaskToBack(true);// 回到上一个工作栈,如果上一个工作栈是最近工作,就会回到桌面
}
@Override
protected void onNewIntent(Intent intent) {Log.i(TAG, "onNewIntent");
super.onNewIntent(intent);
}
@Override
protected void onResume() {super.onResume();
Log.i(TAG, "onResume");
}
@Override
protected void onPause() {Log.i(TAG, "onPause");
super.onPause();}
@Override
protected void onDestroy() {Log.i(TAG, "onDestroy");
super.onDestroy();}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.devnn.demo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Devnn">
<activity
android:name="com.devnn.demo.ActivityA"
android:launchMode="singleInstance"></activity>
<activity
android:name="com.devnn.demo.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>