加载完workspace的数据后,接下来就开始加载所有应用界面的数据了。通过LauncherModel.loadAndBindAllApps()完成所有应用界面的加载过程,代码如下:
private void loadAndBindAllApps() {
if (!mAllAppsLoaded) {
loadAllApps();
synchronized (LoaderTask.this) {
if (mStopped) {
return;
}
mAllAppsLoaded = true;
}
} else {
onlyBindAllApps();
}
}
以上代码分两种情况,如下图:
情况一:数据还未加载时,执行loadAllApps(),不要被它的方法名所误导,该方法实际上完成了load和bind的操作,代码如下:
private void loadAllApps() {
final Callbacks oldCallbacks = mCallbacks.get();
if (oldCallbacks == null) {
// This launcher has exited and nobody bothered to tell us. Just bail.
Log.w(TAG, "LoaderTask running with no launcher (loadAllApps)");
return;
}
final PackageManager packageManager = mContext.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// mBgAllAppsList是AllAppsList类的引用,里面维护了4个
// 列表(data, added, removed, modified),获取到的所有
// 应用数据添加到该列表中,加载前先清楚之前的数据
mBgAllAppsList.clear();
// 返回所有应用的ResolveInfo列表
List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
// Fail if we don't have any apps
if (apps == null || apps.isEmpty()) {
return;
}
// Sort the applications by name
Collections.sort(apps,
new LauncherModel.ShortcutNameComparator(packageManager, mLabelCache));
// Create the ApplicationInfos
for (int i = 0; i < apps.size(); i++) {
ResolveInfo app = apps.get(i);
// new一个AppInfo,获取对应的icon和title,mBgAllAppsList.add(AppInfo info)
// 会把info添加到AllAppList的added和data列表中
mBgAllAppsList.add(new AppInfo(packageManager, app,
mIconCache, mLabelCache));
}
// 下面的过程将把added列表与界面绑定,并清空added列表
final ArrayList<AppInfo> added = mBgAllAppsList.added;
mBgAllAppsList.added = new ArrayList<AppInfo>();
mHandler.post(new Runnable() {
public void run() {
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
callbacks.bindAllApplications(added);
}
}
});
}
private void onlyBindAllApps() {
final Callbacks oldCallbacks = mCallbacks.get();
if (oldCallbacks == null) {
// This launcher has exited and nobody bothered to tell us. Just bail.
Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");
return;
}
// shallow copy,因为mBgAllAppsList只在worker thread中被访问,
// 而bind操作是在main thread中执行的,所以需要进行此copy操作
@SuppressWarnings("unchecked")
final ArrayList<AppInfo> list
= (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
Runnable r = new Runnable() {
public void run() {
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
callbacks.bindAllApplications(list);
}
}
};
// 在main thread中执行bind操作
boolean isRunningOnMainThread = !(sWorkerThread.getThreadId() == Process.myTid());
if (isRunningOnMainThread) {
r.run();
} else {
mHandler.post(r);
}
}
这样数据的加载和绑定过程就结束了,至于在Launcher类中是怎样实现具体的回调方法的,会在后面进行讨论。