今天在重构项目的时候,需要把项目中的核心功能模块更改下,需要再次研究下Launcher,又有了一点收获,这里记录下。
Launcher第一次加载
之前的文章里说过,Launcher桌面主要通过LauncherModel
这个类来加载数据,在这个类中loadAllApps()
方法是用来加载手机上所有的应用显示到桌面上的。这个方法里的代码比较多,这里我就简单的来拿里面的几行重要的来说说。
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// Clear the list of apps
mBgAllAppsList.clear();
List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
通过PM来获取手机上所有应用的启动Activity,ResolveInfo
这个对象是对Activity对象的解析,这里注意这个对象mBgAllAppsList
,这个对象是类AllAppsList
的对象,后面代码中又把apps
集合中的对象拿出来放到了mBgAllAppsList
,代码如下:
mBgAllAppsList.add(new AppInfo(packageManager, apps.get(i), mIconCache, mLabelCache));
可以看到最后真正起作用的是mBgAllAppsList
这个对象中有没有add,这决定了桌面上是否能够显示出这个应用。
Launcher启动完毕以后
上面说了在Launcher第一次启动的时候加载应用的逻辑,那么当Launcher已经启动完毕,我们再安装应用,Launcher是怎么加载应用到桌面上的呢?
同样是在LauncherModel
类中,在这个类中有一个内部类PackageUpdatedTask
,这个类继承了Runnable,类中的run
方法中有一个```switch``语句,如下:
switch (mOp) {
case OP_ADD: //安装应用的时候
...
mBgAllAppsList.addPackage(context, packages[i]);
...
break;
case OP_UPDATE: //应用已经安装,在安装相同的应用的时候
...
mBgAllAppsList.updatePackage(context, packages[i]);
...
break;
case OP_REMOVE: //删除应用的时候
case OP_UNAVAILABLE:
...
mBgAllAppsList.removePackage(packages[i]);
...
break;
}
如注释所说,当Launcher启动完毕以后,我们在安装或者卸载应用,系统会直接进入这个内部类,然后判断是按照还是更新或者是卸载。case
代码中的具体逻辑最后也是通过mBgAllAppsList
这个对象来做不同的操作。
三种情况中,注意在安装和更新这两种情况中,也就是mBgAllAppsList
的addPackage
方法和updatePackage
方法中,看代码都有下面的这段代码:
final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
从方法名字我们可以估计出,这个方法的作用是通过包名找到对应的Activity,点进去,看注释如下:
/**
* Query the package manager for MAIN/LAUNCHER activities in the supplied package.
*/
static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
...
...
}
注释的意思是通过包名来查询启动Activity,而注意返回值中的泛型ResolveInfo
,是解析manifest中<activity>
标签的解析对象。
到这里大概意思就明白了,应用安装的时候,Launcher会通过包名获取到这个应用的启动Activity
信息,然后add
上,应用更新的时候同理,更新一下信息就好。
但是删除会比其他两种操作多了一步,当拖动应用的图标移动到手机上方的垃圾桶的时候,图标此时已经消失,Launcher
会先执行删除图标操作,对应代码中的DeleteDropTarget
类中的completeDrop
方法,这个方法是通过监听调用到的。然后在执行上面switch
语句中的删除逻辑。而在completeDrop
方法中,源码如下:
private void completeDrop(DragObject d) {
...
...
final Runnable checkIfUninstallWasSuccess = new Runnable() {
@Override
public void run() {
mWaitingForUninstall = false;
String packageName = componentName.getPackageName();
List<ResolveInfo> activities = AllAppsList.findActivitiesForPackage(getContext(), packageName);
...
...
}
}
代码较多,看主要的一行,就是上面的最后一行,也调用到了findActivitiesForPackage
这个方法。
总结
1:Launcher在第一次启动的时候,最重要的逻辑是AllAppsList
的add
方法,添加上哪个应用,哪个应用就会显示到桌面上。
2:Launcher启动以后,APP的安装、更新和删除,AllAppsList
对象会调用不同的方法来操作,但最后都会使用到findActivitiesForPackage
方法。