首先是你们熟悉的,在fragment中使用startActivityForResult和requestPermissions的时候,要注意:bash
原本我只是知其然但不知其因此然,可是一次debug让我了解了其中缘由。函数
这样的,我在fragment中发出startActivityForResult请求,在fragment所在的Activity中的onActivityResult打了个断点看一下,这一看就发现了有个问题:fragment中启动的requestCode是0,然而到了activity中的onResult的requestCode变成了65536。this
若是是别的数字的话可能会忽略掉,反正最后是能正常调用fragment的回调的,可是65536?2^16??0xffff+1?这个数字但是很特殊。在看了源码以后终于有了具体的解释,因此来看看发出请求到onResult的过程吧。spa
声明: 如下源码为API 27.1.1debug
能够看到Fragment的startActivityForResult调用一个mHost的方法,这个mHost最后就是调用了FragmentActivity的startActivityFromFragment,那FragmentActivity作了什么呢?
code
requestCode = -1
这是没有result的startActivity用的,暂且不表,下边是重要的部分了,check的函数我也放到一块儿了:
static void checkForValidRequestCode(int requestCode) {
if ((requestCode & 0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
}
...
checkForValidRequestCode(requestCode);
int requestIndex = allocateRequestIndex(fragment);
ActivityCompat.startActivityForResult(
this, intent,
((requestIndex + 1) << 16) + (requestCode & 0xffff), options);
复制代码
首先是检查requestCode,高16位不能有1,即requestcode不能大于0xffff,requestIndex能够理解成fragment的一个标识编号,fragmentActivity来管理的。
重点在这里: 在实际用ActivityCompact启动请求的时候,传入的requestCode并非咱们设置的requestCode了,作了一个转换,((requestIndex + 1) << 16) + (requestCode & 0xffff)
这个转换的意思就是requestIndex+1放在高16位,requestCode的低16位放在新的低16位,这样组成了新的requestCode,写成数学表达式就是:
requestCode = (requestIndex+1)*0xffff+requeseCode
这样新的requestCode就是大于0xffff的了。cdn
首先仍是看源码:blog
首先咱们要明白,Fragment的请求也是先有FragmentActivity来处理的。而后通过上边的分析,咱们大概能够猜想,经过转换requestCode,Fragment和FragmentActivity的请求就被分开了,那onResult的时候也是分开处理的。来看code:开发
分开来看:get
int requestIndex = requestCode>>16;
if (requestIndex != 0) {
requestIndex--;
...
}
复制代码
首先是除以(右移)16,这样剩下的就是高16位,若是不为0的话,就说明requestCode是大于0xffff的,就是咱们Fragment发出的请求,不为0的高16位就是requestIndex。下边就是根据requestIndex找到对应的Fragment了
targetFragment.onActivityResult(
requestCode & 0xffff, resultCode, data);
复制代码
这是真正调用找到的Fragment的onResult的地方,因为请求的时候requestCode通过了转换,因此这里要转换回来,取出低16位就是原来的requestCode。
以上是分析了startActivityForResult的流程,requestPermissions是相似的能够本身去看一遍。源码真的是好东西,Google的工程师也真的厉害,这个逻辑不难可是让我这种新手是很差想出来的。
//做为Android开发的初学者,若是我有错误的地方或者不足的话欢迎你们指正。但愿与你们一同进步。