1 前言
Android 定义了四种启动模式:standard、singleTop、singleTask 和 singleInstance。默认情况下,是 standard 模式。这种模式在绝大多数情况下是没有问题的。因此,在大多数情况下,都不需要去设置启动模式。过度使用启动模式也会给自己的程序带来一些问题,有时候也是很难测试出来的问题。下面就介绍一个过度使用启动模式造成的 bug。
2 正文
2.1 场景介绍
操作步骤如下:
1,通过一个 SplashActivity,打开 MainActivity 页面(启动模式是 singleInstance),把 SplashActivity finish 掉;
2,再通过 MainActivity 打开 SecondActivity 页面(启动模式是 standard);
3,按下 Home 键;
4,点击应用图标,进入应用;
5,再按返回键。
按照我们的想法,应该是显示 MainActivity 页面,但其实是回到了桌面。根本就没有回到 MainActivity 页面。可以看一下,录制的 gif:
那么,这是什么原因呢?又该如何解决这一问题呢?
2.2 分析问题
下边使用一边操作,一边查看任务栈的方式具体看一下。
查看任务栈的命令是:
adb shell dumpsys activity activities
在打开 SecondActivity 后,查看一下任务栈如下:
Display #0 (activities from top to bottom):
Stack #1:
Running activities (most recent first):
TaskRecord{396214d #990 A=com.wzc.chapter_1 U=0 sz=1}
Run #2: ActivityRecord{63fdfc6 u0 com.wzc.chapter_1/.SecondActivity t990}
TaskRecord{2bb1a1 #989 A=com.wzc.chapter_1 U=0 sz=1}
Run #1: ActivityRecord{87511bb u0 com.wzc.chapter_1/.MainActivity t989}
TaskRecord{d9cba29 #886 A=com.android.incallui U=0 sz=1}
Run #0: ActivityRecord{426adbc u0 com.android.incallui/.InCallActivity t886}
mResumedActivity: ActivityRecord{63fdfc6 u0 com.wzc.chapter_1/.SecondActivity t990}
mLastPausedActivity: ActivityRecord{87511bb u0 com.wzc.chapter_1/.MainActivity t989}
Stack #0:
Running activities (most recent first):
TaskRecord{4f9b995 #866 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
mLastPausedActivity: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
从上面可以看出,MainActivity 和 SecondActivity 是在不同的任务栈中,这是因为 MainActivity 设置的启动模式是 singleInstance。
按下 Home 键后,查看一下任务栈如下:
Display #0 (activities from top to bottom):
Stack #0:
Running activities (most recent first):
TaskRecord{4f9b995 #866 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
mResumedActivity: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
Stack #1:
Running activities (most recent first):
TaskRecord{396214d #990 A=com.wzc.chapter_1 U=0 sz=1}
Run #2: ActivityRecord{63fdfc6 u0 com.wzc.chapter_1/.SecondActivity t990}
TaskRecord{2bb1a1 #989 A=com.wzc.chapter_1 U=0 sz=1}
Run #1: ActivityRecord{87511bb u0 com.wzc.chapter_1/.MainActivity t989}
TaskRecord{d9cba29 #886 A=com.android.incallui U=0 sz=1}
Run #0: ActivityRecord{426adbc u0 com.android.incallui/.InCallActivity t886}
mLastPausedActivity: ActivityRecord{63fdfc6 u0 com.wzc.chapter_1/.SecondActivity t990}
这时,我们的应用退到了后台,桌面进入了前台。是这样的。
点击应用图标,进入应用:
Display #0 (activities from top to bottom):
Stack #1:
Running activities (most recent first):
TaskRecord{396214d #990 A=com.wzc.chapter_1 U=0 sz=1}
Run #2: ActivityRecord{63fdfc6 u0 com.wzc.chapter_1/.SecondActivity t990}
TaskRecord{2bb1a1 #989 A=com.wzc.chapter_1 U=0 sz=1}
Run #1: ActivityRecord{87511bb u0 com.wzc.chapter_1/.MainActivity t989}
TaskRecord{d9cba29 #886 A=com.android.incallui U=0 sz=1}
Run #0: ActivityRecord{426adbc u0 com.android.incallui/.InCallActivity t886}
mResumedActivity: ActivityRecord{63fdfc6 u0 com.wzc.chapter_1/.SecondActivity t990}
Stack #0:
Running activities (most recent first):
TaskRecord{4f9b995 #866 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
mLastPausedActivity: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
再按 back 键,我们回到了桌面,查看任务栈:
Display #0 (activities from top to bottom):
Stack #0:
Running activities (most recent first):
TaskRecord{4f9b995 #866 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
mResumedActivity: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
mLastPausedActivity: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
Stack #1:
Running activities (most recent first):
TaskRecord{2bb1a1 #989 A=com.wzc.chapter_1 U=0 sz=1}
Run #1: ActivityRecord{87511bb u0 com.wzc.chapter_1/.MainActivity t989}
TaskRecord{d9cba29 #886 A=com.android.incallui U=0 sz=1}
Run #0: ActivityRecord{426adbc u0 com.android.incallui/.InCallActivity t886}
mLastPausedActivity: ActivityRecord{63fdfc6 u0 com.wzc.chapter_1/.SecondActivity t990 f}
可以看到的是, MainActivity 确实还存在的,但是却没有显示在前台。
这时,再去点击一个应用图标,查看任务栈:
Display #0 (activities from top to bottom):
Stack #1:
Running activities (most recent first):
TaskRecord{2bb1a1 #989 A=com.wzc.chapter_1 U=0 sz=1}
Run #1: ActivityRecord{87511bb u0 com.wzc.chapter_1/.MainActivity t989}
TaskRecord{d9cba29 #886 A=com.android.incallui U=0 sz=1}
Run #0: ActivityRecord{426adbc u0 com.android.incallui/.InCallActivity t886}
mResumedActivity: ActivityRecord{f71f6f8 u0 com.wzc.chapter_1/.MainActivity t994}
mLastPausedActivity: ActivityRecord{9bb5ec8 u0 com.wzc.chapter_1/.SplashActivity t996 f}
Stack #0:
Running activities (most recent first):
TaskRecord{4f9b995 #866 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
mLastPausedActivity: ActivityRecord{34da953 u0 com.huawei.android.launcher/.Launcher t866}
可以看到,显示出来的是原来存在的 MainActivity。
但这是怎么回事呢?
其实,这是由于过度使用启动模式造成的。把 MainActivity 的启动模式设置成 singleTask 就可以了。
最后
本文并没有分析出具体的原因,只是找到了对应的解决办法。欢迎大家留言,一起讨论这个问题。代码地址:https://github.com/jhwsx/android-art-research/tree/master/chapter_1。