Android应用按Home键关闭后无法恢复至ActivityB问题求助
问题:按Home返回后无法恢复到ActivityB界面
我的应用包含4个Activity:SplashActivity、LoginActivity、ActivityA和ActivityB。其中ActivityB由ActivityA启动。SplashActivity作为应用启动页(Launcher),会检查用户登录状态:已登录则启动ActivityA,未登录则启动LoginActivity。
现在遇到的问题是:在ActivityB界面按Home键退出应用,再次打开时却跳转到ActivityA,预期应该直接恢复到ActivityB界面。
现有Manifest配置
<activity android:name=".screen.splash.SplashActivity" android:exported="true" android:launchMode="singleTask" android:theme="${splashTheme}" android:noHistory="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ActivityA" android:exported="false" android:launchMode="singleInstance" /> <activity android:name=".ActivityB" android:exported="false" android:windowSoftInputMode="adjustResize" android:alwaysRetainTaskState="true"/> <activity android:name="LoginActivity" android:exported="false" android:theme="${splashTheme}" />
SplashActivity核心逻辑
if (SettingService.isLogged()) { val intent = Intent(this@SplashActivity, ActivityA::class.java) startActivity(intent) } else { startActivity<LoginActivity>() // org.jetbrains.anko }
问题根源
- ActivityA的
singleInstance模式:这个模式会让ActivityA独占一个独立的任务栈,从ActivityA启动ActivityB时,B会被放入应用的默认任务栈。此时应用存在两个独立任务栈:一个是ActivityA的专属栈,另一个是包含ActivityB的默认栈。 - SplashActivity的启动逻辑缺陷:每次从Launcher打开应用,Splash都会直接启动ActivityA,系统会把ActivityA的任务栈带到前台,而包含ActivityB的默认栈被压在后台,因此显示的是ActivityA。
解决方案
方案1:修正ActivityA的启动模式(推荐)
把ActivityA的launchMode从singleInstance改为默认的standard或singleTop,让A和B处于同一个任务栈中,这样系统就能正确恢复到栈顶的ActivityB:
<activity android:name=".ActivityA" android:exported="false" android:launchMode="standard" /> <!-- 或singleTop,根据业务需求选择 -->
保留ActivityB的alwaysRetainTaskState="true",它能避免系统因内存回收销毁任务栈状态。
方案2:修改SplashActivity的启动逻辑(适配特殊场景)
如果必须保留ActivityA的singleInstance模式,需要在Splash中判断应用是否已有存活的任务栈,有则直接唤起栈顶Activity,而非重新启动ActivityA:
if (SettingService.isLogged()) { val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager var hasExistingTask = false // 遍历当前运行的任务栈 for (task in activityManager.appTasks) { val taskInfo = task.taskInfo if (taskInfo.baseActivity?.packageName == packageName && !taskInfo.topActivity?.className.equals(SplashActivity::class.java.name)) { // 唤起已有任务栈的顶层Activity task.moveToFront() hasExistingTask = true break } } // 没有存活任务栈才启动ActivityA if (!hasExistingTask) { val intent = Intent(this@SplashActivity, ActivityA::class.java) startActivity(intent) } } else { startActivity<LoginActivity>() }
注:API 21及以上推荐用appTasks替代已废弃的getRunningTasks方法。
补充说明
SplashActivity的singleTask和noHistory="true"设置是合理的:singleTask确保Splash不会重复创建实例,noHistory让Splash启动后不会留在任务栈中,无需改动。
内容的提问来源于stack exchange,提问作者Khoa Chau
相关产品推荐
相关产品推荐

