之前我們講了初始化對象,根據硬件參數來獲取佈局,獲取數據參數,所有的都準備好以後,就將進行數據的加載與綁定,本篇文章就來講講Launcher 啓動流程 第六步之LauncherModel的佈局操作。
這一步在Launcher的oncreate啓動流程是最關鍵的一步。這一部分的代碼是:
if (!mModel.startLoader(currentScreen)) {
// If we are not binding synchronously, show a fade in animation when
// the first page bind completes.
mDragLayer.setAlpha(0);
} else {
mWorkspace.setCurrentPage(currentScreen);
setWorkspaceLoading(true);
}
這裏稍微解釋一下,mModel.startLoader(currentScreen),讓LauncherModel開始讀取應用,包括桌面的佈局和allApp的所有應用,將所有應用和圖標放到之前我們規劃好的幾行幾列的格子裏面,返回false表示讀取失敗,這時會走mDragLayer.setAlpha(0);,也就是Launcher的mDragLayer不顯示,也就是桌面時空白的。如果讀取成功就開始加載。
mModel.startLoader(currentScreen)
我們從mModel.startLoader(currentScreen)源碼開始分析
public boolean startLoader(int synchronousBindPage) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
1.InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
synchronized (mLock) {
// Don't bother to start the thread if we know it's not going to do anything
2. if (mCallbacks != null && mCallbacks.get() != null) {
final Callbacks oldCallbacks = mCallbacks.get();
mUiExecutor.execute(new Runnable() {
public void run() {
oldCallbacks.clearPendingBinds();
}
});
3. stopLoader();
4. LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
mBgAllAppsList, synchronousBindPage, mCallbacks);
5. if (mModelLoaded && !mIsLoaderTaskRunning) {
loaderResults.bindWorkspace();
loaderResults.bindAllApps();
loaderResults.bindDeepShortcuts();
loaderResults.bindWidgets();
return true;
} else {
6. startLoaderForResults(loaderResults);
}
}
}
return false;
}
我把代碼分爲了6部分,一一進行分析它的作用:
1.在加載之前先開啓初始化隊列,它會在綁定結束後disabled關掉。
2.判斷綁定回調的Callbacks對象是否存在,如果存在就清理掉所有的綁定回調,方便下面重新綁定數據,此處的oldCallbacks.clearPendingBinds();調用的是Launcher裏面的clearPendingBinds。
- stopLoader(); 如果此時已經有一個Task正在運行,就讓它停止掉。
4.創建oaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
mBgAllAppsList, synchronousBindPage, mCallbacks);創建loaderResults,此類是LauncherModel的輔助類,所有的綁定操作都在此類中完成。
5.判斷當前模型數據是否有效以及LoaderTask是否在運行,條件成立的話就直接進行綁定,如果模型數據無效,以及LoaderTask正在運行,那麼就調用startLoaderForResults(loaderResults);
6.調用startLoaderForResults(loaderResults);,進行數據的加載和綁定
startLoaderForResults(loaderResults);
在這個方法中,一進來就調用了 stopLoader();,也就是在正式加載之前,再一次去確認停止多有正在運行的task,然後創建新的LoaderTask(線程),所以在調用runOnWorkerThread(mLoaderTask);中的run方法時,其實是調用的LoaderTask的run方法。
public void startLoaderForResults(LoaderResults results) {
synchronized (mLock) {
stopLoader();
mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);
runOnWorkerThread(mLoaderTask);
}
}
在LoaderTask的run方法中主要調用了幾個重要的方法,加載數據和綁定的方法。
- 加載和綁定Workspace
loadWorkspace();
mResults.bindWorkspace();
waitForIdle(); - 加載和綁定AllApps
loadAllApps();
mResults.bindAllApps()
waitForIdle(); - 加載和綁定小部件
loadDeepShortcuts();
mResults.bindDeepShortcuts();
waitForIdle(); - 加載和綁定widget
mBgDataModel.widgetsModel.update(mApp, null);
mResults.bindWidgets();
接下來會進行詳細講解數據的加載和綁定,這一部分是最重要的。