Andorid Activity提供了startActivityForResult方法来实现打开另一个页面获取并回调结果的操作。但在某些情况下,startActivityForResult会出现无效的情况。
相关书籍中的解释
在《Android群英传》书中有这么一段话
"如果在一个 singleTop 或者 singleInstance 的 ActivityA 中通过 startActivityForResult()方法来启动另一个 ActivityB,那么系统将直接返回 Activity.RESULT_CANCELED 而不会再去等待返回,这是由于系统在 Framework 层做了对这两种启动模式的限制,因为 Android 开发者认为,不同 Task 之间默认是不能传递数据的,如果一定要传递,那则只能通过 Intent 来绑定数据。 "
首先,说明下这句话适用于Android 5.0(api 21)以下的系统,在5.0及以上的系统中不存在该问题。也就是startActivityForResult()正常工作。
其次结合自己开发测试的实例,发现上面singleTop应该换成singleTask,因为singleTop无关不同的Task,而singleInstance和singleTask都是有关不同task操作的,singleTop模式下并没有出现Activity.RESULT_CANCELED的情况。
Android Api关于startActivityForResult的解释
Launch an activity for which you would like a result when it finished. When this activity exits, your onActivityResult() method will be called with the given requestCode. Using a negative requestCode is the same as calling startActivity(Intent)
(the activity is not launched as a sub-activity).
Note that this method should only be used with Intent protocols that are defined to return a result. In other protocols (such as ACTION_MAIN
or ACTION_VIEW
), you may not get the result when you expect. For example, if the activity you are launching uses FLAG_ACTIVITY_NEW_TASK
, it will not run in your task and thus you will immediately receive a cancel result.
这里说明了startActivityForResult()只适用于Intent显式启动Activity。而且在FLAG_ACTIVITY_NEW_TASK情况下,也就是新建任务栈时来存放待启动Activity时,startActivityForResult()是无效的,这里也说明了不同task之间没有效果,经过测试,同样在api 21以下是这样,以上不是这样了,但文档上没有标注。
测试验证
测试的例子很简单,新建一个android项目,里面三个Activity,分别进行设置不同launchMode进行startActivityForResult()跳转,并且在不同版本机型下测试。以下记录下测试结果
(✅表明在onActivityResult()中正常获取结果;❌表示在onActivityResult()中立即获取了Activity.RESULT_CANCELED的结果):
startActivityForResult | api>=21 | api<=19 |
---|---|---|
A(standard)---->B(singleTop) | ✅ | ✅ |
A(standard)---->B(singleTask) | ✅ | ❌ |
A(standard)---->B(singleInstance) | ✅ | ❌ |
A(singleTop)---->B(standard) | ✅ | ✅ |
A(singleTask)---->B(standard) | ✅ | ❌ |
A(singleInstance)---->B(standard) | ✅ | ❌ |
结果表明在21之后,startActivityForResult()做了处理,适用于所有的启动模式了。
在实际开发中需要注意到这里的适配,容错。
其他
《Android群英传》p202