【源码剖析】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();

接下来会进行详细讲解数据的加载和绑定,这一部分是最重要的。

你可能感兴趣的:(【源码剖析】Launcher 8.0 源码 (13) --- Launcher 启动流程 第六步之LauncherModel的布局操作(一) 整体概述)