之前我们讲了初始化对象,根据硬件参数来获取布局,获取数据参数,所有的都准备好以后,就将进行数据的加载与绑定,本篇文章就来讲讲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();
接下来会进行详细讲解数据的加载和绑定,这一部分是最重要的。