resolveActivity解析
resolveActivity是Activity创建过程中非常重要的一个函数,会在ActivityStack
的startActivityMayWait
中调用。这个函数的主要作用就是根据intent去收集需要启动的activity的信息,看下函数的原型:
ActivityInfo resolveActivity(Intent intent, String resolvedType, boolean debug, String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { // Collect information about the target of the Intent. ActivityInfo aInfo; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { aInfo = null; } if (aInfo != null) { // Store the found target back into the intent, because now that // we have it we never want to do this again. For example, if the // user navigates back to this point in the history, we should // always restart the exact same activity. intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); // Don't debug things in the system process if (debug) { if (!aInfo.processName.equals("system")) { mService.setDebugApp(aInfo.processName, true, false); } } if (profileFile != null) { if (!aInfo.processName.equals("system")) { mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, profileFile, profileFd, autoStopProfiler); } } } return aInfo;
}
为了不影响对resolveActivity
的分析,需要把Activity启动过程中传到此函数的参数说明一下,当我们点击launcher界面启动一个Activity的时候,intent就是我们正常启动启动Activity时的intent;其余的boolean类型的值为false,非boolean类型的值为null。
函数的关键在AppGlobals.getPackageManager().resolveIntent(intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS)
。AppGlobals这个变量提供了一个静态方法,方便应用可以获取系统的函数调用接口。最重要的部分应该就是getPackageManager().resolveInten
了,ok,到PackageManagerService看下resolveIntent这个方法。
public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags) { List query = queryIntentActivities(intent, resolvedType, flags); return chooseBestActivity(intent, resolvedType, flags, query); }
resolveIntent经过了两个步骤,首先根据传递的信息选出符合条件的集合,然后从集合中找出最合适的信息。第一步queryIntentActivities
根据intent, resolveType,flag信息选出可能存在的Activity的信息;chooseBestActivity
会从第一步的信息的集合中选择最符合条件的Activity,如果chooseBestActivity
选出的符合条件的Activity不止一个,则会让用户选择具体需要启动哪个Activity。可以看下chooseBestActivity
的实现:
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, int flags, List query) { if (query != null) { final int N = query.size(); /**如果根据条件只找到了一个Activity,则直接返回*/ if (N == 1) { return query.get(0); } else if (N > 1) { /**根据条件找到了多个Activity*/ // If there is more than one activity with the same priority, // then let the user decide between them. ResolveInfo r0 = query.get(0); ResolveInfo r1 = query.get(1); if (DEBUG_INTENT_MATCHING) { Log.d(TAG, r0.activityInfo.name + "=" + r0.priority + " vs " + r1.activityInfo.name + "=" + r1.priority); } /**如果第一个Activity有更高的优先级,或者default设置不相同,则返回第一个Activity*/ // If the first activity has a higher priority, or a different // default, then it is always desireable to pick it. if (r0.priority != r1.priority || r0.preferredOrder != r1.preferredOrder || r0.isDefault != r1.isDefault) { return query.get(0); } // If we have saved a preference for a preferred activity for // this Intent, use that. ResolveInfo ri = findPreferredActivity(intent, resolvedType, flags, query, r0.priority); if (ri != null) { return ri; } return mResolveInfo; } } return null; }
多有多个Activity符合查询条件时,最终会进入findPreferredActivity
找到最合适的Activity。findPreferredActivity
最终会调用findPersistentPreferredActivityLP
这个函数。 由于正在分析Activity的启动流程,这个函数我还没有去分析,个人猜想可能是这样一个流程,类似于我们在android上打开一个网页,如果你有多个浏览器可以去打开网页,那么android弹出对话框,让用户选择使用哪个浏览器去打开网页;如果用户选择了一个浏览器并且勾选了总是
,那么下次再打开网页的时候就会启动已经默认的浏览器,如果用户没有勾选总是
,则每次打开网页的时候就会弹出对话框让用户选择。
更多相关文章
- [android] android下文件访问的权限
- 基于Android的Linux内核的电源管理:Early Suspend
- Android(安卓)技巧 - 取得当前活动的activity的class name / pac
- Android用户登录数据存储的三种方式
- Android(安卓)游戏开发中 OnTouchEvent() 触屏事件的性能优化
- React Native项目组织结构介绍
- Android控制ScrollView滚动
- Android(安卓)camera系统开发之IPC (五)
- 深拷贝和浅拷贝