一、 why ?

  由于才疏学浅,在开发中requestCode的让我很困惑。困惑是因为什么呢,是因为弄混了。要想弄明白,不困惑,来想一想用到requestCode的地方:

  ① startActivityForResult开启另一个Activity的时候:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
  }

  ② 请求权限的时候:

public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can reqeust only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
}
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}

(1)首先来看startActivityForResult()的requestCode:

  通过查看源码发现:在Activity中startActivityForResult() 和Activity的子类FragmentActivity中的startActivityForResult()是不一样的,代码展示区别:

/**
* Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
* with no options.
*
* @param intent The intent to start.
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
*
* @throws android.content.ActivityNotFoundException
*
* @see #startActivity
*/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
/**
* Modifies the standard behavior to allow results to be delivered to fragments.
* This imposes a restriction that requestCode be <= 0xffff.
*/
@Override
public void startActivityForResult(Intent intent, int requestCode) {
// If this was started from a Fragment we've already checked
     // the upper 16 bits were not in
// use, and then repurposed them for the Fragment's index.
if (!mStartedActivityFromFragment) {
if (requestCode != -1) {
checkForValidRequestCode(requestCode);
}
}
super.startActivityForResult(intent, requestCode);
}
/**
* Checks whether the given request code is a valid code by masking it with 0xffff0000. Throws
* an {@link IllegalArgumentException} if the code is not valid.
*/
static void checkForValidRequestCode(int requestCode) {
if ((requestCode & 0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
}
 

通过以上代码的比较我们知道,会造成下面的错误,是FragmentActivity添加的限制,而Activity中没有该限制,这里解决了一点点疑惑:

java.lang.IllegalArgumentException: Can only use lower  bits for requestCode

所以这里总结一下:在startActivityForResult()中的resquestCode的限制是  0 <= requestCode <= 216 ,小于零会造成什么问题,你可以试试,我没有尝试。

(2)再来看ActivityCompat请求权限中的requestCode:

public static void requestPermissions(final @NonNull Activity activity,
final @NonNull String[] permissions, final int requestCode) {
if (Build.VERSION.SDK_INT >= 23) {
ActivityCompatApi23.requestPermissions(activity, permissions, requestCode);
} else if (activity instanceof OnRequestPermissionsResultCallback) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
final int[] grantResults = new int[permissions.length]; PackageManager packageManager = activity.getPackageManager();
String packageName = activity.getPackageName(); final int permissionCount = permissions.length;
for (int i = 0; i < permissionCount; i++) {
grantResults[i] = packageManager.checkPermission(
permissions[i], packageName);
} ((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult(
requestCode, permissions, grantResults);
}
});
}
}

由源码可以知道:当sdk >=23的时候,会走 ActivityCompatApi23.requestPermissions(activity, permissions, requestCode),来看看它干了什么:

public static void requestPermissions(Activity activity, String[] permissions,
int requestCode) {
if (activity instanceof RequestPermissionsRequestCodeValidator) {
((RequestPermissionsRequestCodeValidator) activity)
.validateRequestPermissionsRequestCode(requestCode);
}
activity.requestPermissions(permissions, requestCode);
}

如果Activity实现了接口RequestPermissionsRequestCodeValidator 就会对requestCode进行判断,天啊,终于说到它了。validateRequestPermissionsRequestCode 见名之意,它对requestCode作了限制,看看FragmentActivity实现的该接口是怎么限制的:checkForValidRequestCode() 这个方法是不是很熟悉:上面就有看看吧,看来限制是一样的: 请求权限              requestCode <= 216

 @Override
public final void validateRequestPermissionsRequestCode(int requestCode) {
// We use 16 bits of the request code to encode the fragment id when
// requesting permissions from a fragment. Hence, requestPermissions()
// should validate the code against that but we cannot override it as
// we can not then call super and also the ActivityCompat would call
// back to this override. To handle this we use dependency inversion
// where we are the validator of request codes when requesting
// permissions in ActivityCompat.
if (!mRequestedPermissionsFromFragment
&& requestCode != -1) {
checkForValidRequestCode(requestCode);
}
}

你会不会以为这个限制只有在sdk >=23以上才有,那就错了。我们来看看小于23时的分支会直接走到onRequestPermissionsResult(),来看看它:哇,同样的限制。

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
int index = (requestCode >> 16) & 0xffff;
if (index != 0) {
index--; String who = mPendingFragmentActivityResults.get(index);
mPendingFragmentActivityResults.remove(index);
if (who == null) {
Log.w(TAG, "Activity result delivered for unknown Fragment.");
return;
}
Fragment frag = mFragments.findFragmentByWho(who);
if (frag == null) {
Log.w(TAG, "Activity result no fragment exists for who: " + who);
} else {
frag.onRequestPermissionsResult(requestCode & 0xffff, permissions, grantResults);
}
}
}

二、总结:

FragmentActivity是对Activtiy的一层包装,requestCode的限制是在它里面添加的,而Activity本身对requestCode是没有限制的。所以如果发现有的requestCode大于216仍然能通过,不要疑惑,你懂得!

Android requestCode的限制的更多相关文章

  1. Android requestcode resultcode的作用

    requestcode 一个页面的不同事件,激发不同的函数,startActivityForResult中传入不同的请求码的值以调用下一个界面,在被调用界面结束返回第一个界面时,请求码会自动返回(自动 ...

  2. android startActivityForResult(Intent intent, int requestCode) 整理与总结! .

    假设有两个Activity,主界面A,功能界面B,由A启动B,并传数据给B,B在经过处理后把数据传回给A. 先是A传B: Bundle bundle = new Bundle();bundle.put ...

  3. Android FragmentActivity 嵌套 Fragment 调用startActivityForResult返回的requestCode错误

    Android FragmentActivity 嵌套 Fragment 调用startActivityForResult返回的requestCode错误 此时,要在调用startActivityFo ...

  4. android小知识之fragment中调用startActivityForResult(Intent intent,int requestcode)所遇到的问题

    大家都知道对于Activity和Fragment都可以注册OnActivityResult()方法,但是要注意几点: a.当activity和fragment都注册了OnActivityResult( ...

  5. Android开发 Fragment中调用startActivityForResult返回错误的requestCode

    返回错误的requestCode返回值为65537,在Fragment里调用startActivityForResult,就必须在Fragment里处理onActivityResult.

  6. Android onActivityResult 设置requestCode 返回的code不对

    今天在项目里用到 Intent intent=new Intent(getActivity(), Test.class);startActivityForResult(intent, 1); onAc ...

  7. Android 6.0 权限知识学习笔记

    最近在项目上因为6.0运行时权限吃了亏,发现之前对运行时权限的理解不足,决定回炉重造,重新学习一下Android Permission. 进入正题: Android权限 在Android系统中,权限分 ...

  8. Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...

  9. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

随机推荐

  1. MySQL笔记(八)存储过程练习&补充

    存储过程有什么优缺点?为什么要用存储过程?或者在什么情况下才用存储过程? 最直白的好处是存储过程比较快. 1.利用存储过程,给Employee表添加一条业务部门员工的信息. DROP PROCEDUR ...

  2. Python基本数据类型——字典

    字典 dict 字典是Python的另一种有序的可变数据结构,且可存储任意类型对象. 字典是一种键值对的数据容器,每个键值(key:value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典 ...

  3. bzoj4566 / P3181 [HAOI2016]找相同字符

    P3181 [HAOI2016]找相同字符 后缀自动机 (正解应是广义后缀自动机) 并不会广义后缀自动机. 然鹅可以用普通的后缀自动机.   我们先引入一个问题:算出从一个串内取任意两个不重合子串完全 ...

  4. Linux 添加网卡

    Linux 添加网卡 1.写入网卡配置 vim /etc/sysconfig/network-scripts/ifcfg-eth1 # 网卡名字 DEVICE=eth1 # 网卡类型 TYPE=Eth ...

  5. Spring Boot中注入配置文件application.properties中的list 对象参数

    例如要注入下列参数: dyn.spring.datasources[0].name=branchtadyn.spring.datasources[0].driverClassName=oracle.j ...

  6. maven单元测试报java.lang.IllegalStateException: Failed to load ApplicationContext

    报这个异常java.lang.IllegalStateException: Failed to load ApplicationContext的时候,通常是因为applicationContent.x ...

  7. windows下常用的几个批处理脚本

    1.windows下对比两个文件内容,有差异则执行一个任务: 适用场景:比如你的数据库备份结果的日志每天会形成一个文件,如下图,你可以通过此脚本检测到文件的变化,并执行发送告警邮件通知你数据库备份异常 ...

  8. Django模版语言的复用 1. include标签--模版导入 2.inclusion_tag自定义标签--模版导入 3.母版

    include标签--模版导入 ''' 前提:项目中,往往会出现多个页面拥有一个或几个相同的页面版块,或是一个页面多个页面版块是相同的 如何运用:可以将多个样式标签的集合进行封装,对外提供版块的名字( ...

  9. and与or的用法

    #1.判断下列语句的True和False # 1)1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 结果为T ...

  10. python第一阶段总结(1)

    python3第一阶段的总结 首先申明一下,本人是看网络课程“老男孩”过来写博客的,想把自己学到的东西分享一下.同时给老男孩打个广告,其教学水平真的挺好的.仅据我个人多年的学习评价. 好,接下来是我对 ...