resolveActivity解析

resolveActivity是Activity创建过程中非常重要的一个函数,会在ActivityStackstartActivityMayWait中调用。这个函数的主要作用就是根据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<ResolveInfo> 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<ResolveInfo> 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弹出对话框,让用户选择使用哪个浏览器去打开网页;如果用户选择了一个浏览器并且勾选了总是,那么下次再打开网页的时候就会启动已经默认的浏览器,如果用户没有勾选总是,则每次打开网页的时候就会弹出对话框让用户选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值