加載完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類中是怎樣實現具體的回調方法的,會在後面進行討論。