应用安装、更新、卸载时的数据加载
上一章墨香带你学Launcher之(三)-绑定屏幕、图标、文件夹和Widget讲了桌面CellLayout、图标、文件夹以及Widget的绑定流程,这个主要是第一次加载时的绑定流程,那么当用户安装新的应用,或者更新应用,或者卸载应用时桌面是如何处理的,今天我们来学习一下这个流程。
我们知道应用的安装和更新都是通过应用市场来启动,而应用的卸载是通过桌面或者系统的app管理来启动的,因此我们将应用的安装和更新一起来讲,而应用的卸载单独来讲。首先我们先看一下应用的安装和更新时桌面的数据加载。
应用安装和更新
当我们通过应用市场安装或者更新应用时,会调用系统的安装界面,并执行安装程序,在应用安装或者更新完成后系统会发出对应的广播,通过对应广播Launcher会执行相应的加载程序。首先我们看一个App管理的兼容库:LauncherAppsCompat,这里面有一个接口和一些抽象方法,我们用的到底主要是这个接口还有两个抽象方法:
接口类:
public interface OnAppsChangedCallbackCompat {
void onPackageRemoved(String packageName, UserHandleCompat user);
void onPackageAdded(String packageName, UserHandleCompat user);
void onPackageChanged(String packageName, UserHandleCompat user);
void onPackagesAvailable(String[] packageNames, UserHandleCompat user, boolean replacing);
void onPackagesUnavailable(String[] packageNames, UserHandleCompat user, boolean replacing);
}
从这个接口中的方法我们可以了解到这个是对App移除、添加、改变、可用和不可用的各种情况的处理。
抽象方法:
public abstract void addOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
public abstract void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
这两个方法主要是添加、删除App管理的监听。
我们看到LauncherAppsCompat是一个抽象类,那么我们看看到底哪里实现了这里的方法:
通过上图我们看到有两个类继承了这个抽象类:LauncherAppsCompatV16和LauncherAppsCompatVL,这两个类其实是针对不同的API版本做了兼容处理,LauncherAppsCompatV16是Android的sdk版本高于16低于21的系统的处理,LauncherAppsCompatVL是sdk版本高于21的系统的处理,那么从21以上到底做了哪些不同处理我们简单看一下,在他们的父类中有一个抽象方法:
public abstract List<LauncherActivityInfoCompat> getActivityList(String packageName,
UserHandleCompat user);
这个方法是获取系统中所有应用的方法,我们看看在不同版本是怎么处理的,首先看一下LauncherAppsCompatV16中:
public List<LauncherActivityInfoCompat> getActivityList(String packageName,
UserHandleCompat user) {
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mainIntent.setPackage(packageName);
List<ResolveInfo> infos = mPm.queryIntentActivities(mainIntent, 0);
List<LauncherActivityInfoCompat> list =
new ArrayList<LauncherActivityInfoCompat>(infos.size());
for (ResolveInfo info : infos) {
list.add(new LauncherActivityInfoCompatV16(mContext, info));
}
return list;
}
这个方法是通过包管理来查询所有的应用,然后根据循环来收集所有的应用信息。
而LauncherAppsCompatVL中:
public List<LauncherActivityInfoCompat> getActivityList(String packageName,
UserHandleCompat user) {
List<LauncherActivityInfo> list = mLauncherApps.getActivityList(packageName,
user.getUser());
if (list.size() == 0) {
return Collections.emptyList();
}
ArrayList<LauncherActivityInfoCompat> compatList =
new ArrayList<LauncherActivityInfoCompat>(list.size());
for (LauncherActivityInfo info : list) {
compatList.add(new LauncherActivityInfoCompatVL(info));
}
return compatList;
}
这个方法中是通过mLauncherApps直接过去的列表信息,那么我们看看api文档,这个LauncherApp是个什么时候开始有的:
我们可以看到是Api为21时才开始添加的,我们看一下这个类中主要的方法;
public class LauncherApps {
...
public static abstract class Callback {
abstract public void onPackageRemoved(String packageName, UserHandle user);
abstract public void onPackageAdded(String packageName, UserHandle user);
abstract public void onPackageChanged(String packageName, UserHandle user);
abstract public void onPackagesAvailable(String[] packageNames, UserHandle user,
boolean replacing);
abstract public void onPackagesUnavailable(String[] packageNames, UserHandle user,
boolean replacing);
}
public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {
...
}
private IOnAppsChangedListener.Stub mAppsChangedListener = new IOnAppsChangedListener.Stub() {
@Override
public void onPackageRemoved(UserHandle user, String packageName)
throws RemoteException {
...
}
@Override
public void onPackageChanged(UserHandle user, String packageName) throws RemoteException {
...
}
@Override
public void onPackageAdded(UserHandle user, String packageName) throws RemoteException {
...
}
@Override
public void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing)
throws RemoteException {
...
}
@Override
public void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing)
throws RemoteException {
...
}
}
};
private static class CallbackMessageHandler extends Handler {
...
@Override
public void handleMessage(Message msg) {
if (mCallback == null || !(msg.obj instanceof CallbackInfo)) {
return;
}
CallbackInfo info = (CallbackInfo) msg.obj;
switch (msg.what) {
case MSG_ADDED:
mCallback.onPackageAdded(info.packageName, info.user