【源碼剖析】Launcher 8.0 源碼 (13) --- Launcher 啓動流程 第六步之LauncherModel的佈局操作(一) 整體概述

之前我們講了初始化對象,根據硬件參數來獲取佈局,獲取數據參數,所有的都準備好以後,就將進行數據的加載與綁定,本篇文章就來講講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。

  1. 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();

接下來會進行詳細講解數據的加載和綁定,這一部分是最重要的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章