v4包下的fragment调用 startActivityForResult 时闪退

顺便科普一下:

过去support-v4库是一个jar包,24.2.0版本开始,将support-v4库模块化为多个jar包,


在Android Support Library 24.2.0及之后的版本中,为了增强效率和减小APK的大小起见,Android将V4包从一个独立的依赖包拆分成
v4 compat library、
v4 core-utils library、
v4 core-ui library、
v4 media-combat library、
v4 fragment library
以上这5个包,这么做是为了减少APK包大小,你需要用哪个模块就引入哪个模块

如下图:

v4包下的fragment调用 startActivityForResult 时闪退

v4包下的fragment调用 startActivityForResult 时闪退


v4包下的fragment调用 startActivityForResult 时闪退

相关推荐:

1、一篇很详细的介绍 Fragment 的文章

https://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653579375&idx=1&sn=4f80a50961329e19cad6cd0e1bff20d9&chksm=84b3ba68b3c4337e28a870d6338fa3035d299a2aff2f3bf3f82304417aa7a83deab0b95031e6&mpshare=1&scene=23&srcid=1026aSKi4Kb6b1ynJsuQHsQ7#rd

2、彻底弄清support支持库,以及v4 v7重复依赖问题深究

https://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650825239&idx=1&sn=dc3e8ad76dee99dc7eb213067e18c667&chksm=80b7b689b7c03f9f60f404b5e239c22a6da121d09f70180a8c7f30406c500f7548576f7f17cd&mpshare=1&scene=23&srcid=0409IqZrekhToB9txLVuIBu8#rd




结论:
v4包下的 fragment 调用 startActivityForResult 时, requestCode 取值范围必须 [0, 65535]的整数 。  其中support-v7包 使用的是  com.android.support:appcompat-v7:24.2.0 版本。 否则 直接 闪退。


现象:

在Fragment 中调用  startActivityForResult(intent, 65536);  app直接闪退,  support-v7包 使用的是 com.android.support:appcompat-v7:24.2.0版本

v4包下的fragment调用 startActivityForResult 时闪退



原因:
在fragment 通过 startForResult 启动 新Activity时, 系统层 将  requestCode 的 低16位  用于存储  用户设置的 值 , 高16位用于存储 系统计算出的 requestIndex。 因此 用户的 requestCode 的值 不能 超过 2的16次方-1,即65535。


在Activity 调用 onActivityResult 时,系统从 requestCode的高16位中 拿出 index,再转换成 当时发起这个 start 的 fragment 所对应的 tag,  最后通过 tag 找出 这个fragment,执行它的 fragment.onActivityResult().

因此需要注意:

如果fragment所在activity中重写了onActivityResult,那么activity中的onActivityResult一定要加上super.onActivityResult(requestCode, resultCode, data),否则也无法传进Fragment中。



查看 FragmentActivity.java 源码  ,下图 查看的 combat包 源码版本 是com.android.support:appcompat-v7:24.2.0

v4包下的fragment调用 startActivityForResult 时闪退



记录一个bug

 在fragment 中 startForResult 启动时,  这个 fragment 和 它所在的 Activity都会收到 onActivityResult 的回调,

但 它所在的Activity 中的 requestCode 不准确的,这是系统层的问题。 

 可以通过 往 setResult 的 intent 中 存入 requetCode 来 满足业务需求, 取出时不直接比较requestCode,而是比较intent.getString("requestCode") 来识别特定的业务需求

v4包下的fragment调用 startActivityForResult 时闪退