Launcher3之新安装应用加载过程

引言

对于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<>();/<appinfo>


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,/<launcheractivityinfo>


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) {/<appinfo>


mAppsView.getAppsStore().addOrUpdateApps(apps);


if (mLauncherCallbacks != null) {


mLauncherCallbacks.bindAppsAddedOrUpdated(apps);


}


}


}


最终会通过AllAppsStore的addOrUpdateApps方法去通知AllApps界面刷新。

v


分享到:


相關文章: