引言
对于Android手机用户来说,每天接触着各式各样的手机应用,应用的安装、更新和卸载操作并不陌生,更不用说看这篇文章的开发者了。那么,当一个新应用安装完成以后,launcher中需要做哪些事情,来完成向用户提供应用图标入口的功能呢?
该篇我就跟大家来探讨下,新应用安装后,launcher中的加载过程。
Workspace新应用加载过程分析
1、外部交互接口
应用安装的实现并不是launcher完成的,而是系统PackageManagerService完成的,但是launcher会向系统注册回调接口,当完成应用安装后,launcher会收到接口回调,进而处理后续事宜。
先来看下相关接口和实现(为了避免干扰,这边省略了其他接口):
public class LauncherAppsCompatVL extends LauncherAppsCompat {
protected final LauncherApps mLauncherApps;
protected final Context mContext;
@Override
public void addOnAppsChangedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {
WrappedCallback wrappedCallback = new WrappedCallback(callback);
...
mLauncherApps.registerCallback(wrappedCallback);//注册
}
//接口实现
private static class WrappedCallback extends LauncherApps.Callback {
private final LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback;
public WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {
mCallback = callback;
}
@Override
public void onPackageAdded(String packageName, UserHandle user) {
mCallback.onPackageAdded(packageName, user);
}
}
}
LauncherApps是SDK开放给launcher使用的接口类,launcher实现了LauncherApps.Callback接口,然后通过registerCallback方法注册监听,当发生应用改变时,就可以收到回调,进而进行相应处理。
在新应用安装完成后,WrappedCallback实现类的onPackageAdded方法会被回调,再交给OnAppsChangedCallbackCompat接口实现处理。
2、内部回调实现
接着看看launcher中OnAppsChangedCallbackCompat的实现到底来自何方,代码如下:
public class LauncherModel extends BroadcastReceiver
implements LauncherAppsCompat.OnAppsChangedCallbackCompat {
...
@Override
public void onPackageAdded(String packageName, UserHandle user) {
int op = PackageUpdatedTask.OP_ADD;
enqueueModelUpdateTask(new PackageUpdatedTask(op, user, packageName));
}
...
}
public class LauncherAppState {
private LauncherAppState(Context context) {
...
LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel);
...
}
}
原来LauncherModel中实现了OnAppsChangedCallbackCompat接口,并且在LauncherAppState构造函数中完成了注册监听,那么,我们就从LauncherModel中的onPackageAdded接口实现继续追踪吧。
onPackageAdded中唯一调用的方法enqueueModelUpdateTask,看下它的实现:
public void enqueueModelUpdateTask(ModelUpdateTask task) {
task.init(mApp, this, sBgDataModel, mBgAllAppsList, mUiExecutor);
runOnWorkerThread(task);
}
就两行代码,主要做的事情就是,保证任务在工作线程执行,具体完成任务是PackageUpdatedTask。
3、PackageUpdatedTask类
看下PackageUpdatedTask源码中的注释:
/**
* Handles updates due to changes in package manager (app installed/updated/removed)
* or when a user availability changes.
*/
public class PackageUpdatedTask extends BaseModelUpdateTask {
从注释可以看出,PackageUpdatedTask类处理了应用安装、更新和卸载等过程,我们这里只对新应用安装做下分析,其他过程分析类似。
先来看下PackageUpdatedTask的类继承关系:
下面看下OP_ADD,也就是新应用安装时,代码的真正实现:
public class PackageUpdatedTask extends BaseModelUpdateTask {
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
...
final String[] packages = mPackages;
final int N = packages.length;
FlagOp flagOp = FlagOp.NO_OP;
...
switch (mOp) {
case OP_ADD: {
for (int i = 0; i < N; i++) {
...
iconCache.updateIconsForPkg(packages[i], mUser);
...
appsList.addPackage(context, packages[i], mUser);
...
}
flagOp = FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
}
}
final ArrayList<AppInfo> addedOrModified = new ArrayList<>();
addedOrModified.addAll(appsList.added);
appsList.added.clear();
addedOrModified.addAll(appsList.modified);
appsList.modified.clear();
...
if (!addedOrModified.isEmpty()) {
scheduleCallbackTask(new CallbackTask() {
@Override
public void execute(Callbacks callbacks) {
callbacks.bindAppsAddedOrUpdated(addedOrModified);
}
});
...
}
}
]
execute方法中,主要做了两件事:
- a. 通过appsList.addPackage方法将新应用信息缓存到AllAppsList
public void addPackage(Context context, String packageName, UserHandle user) {
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
final List<LauncherActivityInfo> matches = launcherApps.getActivityList(packageName,
user);
for (LauncherActivityInfo info : matches) {
add(context,new AppInfo(context, info, user), info,false);
}
}
public void add(Context context,AppInfo info, LauncherActivityInfo activityInfo,boolean isUpdate) {
...
data.add(info);
boolean success = added.add(info);
...
}
- b. 通过bindAppsAddedOrUpdated方法回调launcher,进行界面更新的处理。
public final void scheduleCallbackTask(final CallbackTask task) {
final Callbacks callbacks = mModel.getCallback();
mUiExecutor.execute(() -> {
Callbacks cb = mModel.getCallback();
if (callbacks == cb && cb != null) {
task.execute(callbacks);
}
});
}
scheduleCallbackTask方法有两个作用:1.切换到UI线程去处理bindAppsAddedOrUpdated回调;2. 通过mModel.getCallback向execute传参
最后看看bindAppsAddedOrUpdated在Launcher中的实现:
public class Launcher extends BaseDraggingActivity implements LauncherExterns,
LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate{
@Override
public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps) {
mAppsView.getAppsStore().addOrUpdateApps(apps);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.bindAppsAddedOrUpdated(apps);
}
}
}
最终会通过AllAppsStore的addOrUpdateApps方法去通知AllApps界面刷新。
小结
以上就是AOSP launcher3中新应用的加载过程,如果新应用安装时,有自动添加图标到桌面的需求,或者实现的是单层launcher,没有AllApps的场景,还需要向Workspace添加图标和小部件。