Launcher 在我个人看来是简单且又复杂的一个模块。 简单是只要认真看,基本能看通UI部分大体逻辑,稍微动手改一下,就能看到效果,成就感大大滴有。 复杂是和SystemUI之间强绑定,看起来让我这菜狗CPU嗡嗡的。

Launcher 继承StatefulActivity 实现Callbacks 涉及类如下
LauncherModelLauncherAppStateLoaderTaskLoaderResults
进入Launcher 的onCreate 看一下
            
            
              java
              
              
            
          
          //packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
protected void onCreate(Bundle savedInstanceState) {
LauncherAppState app = LauncherAppState.getInstance(this);
mModel = app.getModel();
if (!mModel.addCallbacksAndLoad(this)) {
    if (!internalStateHandled) {
        // If we are not binding synchronously, pause drawing until initial bind complete,
        // so that the system could continue to show the device loading prompt
        mOnInitialBindListener = Boolean.FALSE::booleanValue;
    }
}
}
        LauncherAppState 采用单例模式 ,在双构造里面引入了老演员InvariantDeviceProfile。 到现在大家不用理解太多。反正知道LauncherAppState里面是嘛都有啊~。
            
            
              java
              
              
            
          
          public LauncherAppState(Context context) {
    this(context, LauncherFiles.APP_ICONS_DB);
}
public LauncherAppState(Context context, @Nullable String iconCacheFileName) {
    mContext = context;
//出来吧 神龙 详情看第一篇
    mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(context);
    mIconProvider = new LauncherIconProvider(context);
    mIconCache = new IconCache(mContext, mInvariantDeviceProfile,
            iconCacheFileName, mIconProvider);
            //出来吧我的model
    mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext),
            iconCacheFileName != null);
    mOnTerminateCallback.add(mIconCache::close);
}
        LauncherModel
            
            
              java
              
              
            
          
          LauncherModel(@NonNull final Context context, @NonNull final LauncherAppState app,
        @NonNull final IconCache iconCache, @NonNull final AppFilter appFilter,
        final boolean isPrimaryInstance) {
    mApp = app;
    mBgAllAppsList = new AllAppsList(iconCache, appFilter);
    mModelDelegate = ModelDelegate.newInstance(context, app, mBgAllAppsList, mBgDataModel,
            isPrimaryInstance);
}
        LoaderTask其中的mModelDelegate 是使用的 LauncherModel 传递过来的单例对象。
            
            
              java
              
              
            
          
          public LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel,
        ModelDelegate modelDelegate, LoaderResults results) {
    mApp = app;
    mBgAllAppsList = bgAllAppsList;
    mBgDataModel = dataModel;
    mModelDelegate = modelDelegate;
    mResults = results;
    mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class);
    mUserManager = mApp.getContext().getSystemService(UserManager.class);
    mUserCache = UserCache.INSTANCE.get(mApp.getContext());
    mSessionHelper = InstallSessionHelper.INSTANCE.get(mApp.getContext());
    mIconCache = mApp.getIconCache();
}
        我们直接进入mModel.addCallbacksAndLoad 这段代码。
            
            
              java
              
              
            
          
          public boolean addCallbacksAndLoad(@NonNull final Callbacks callbacks) {
    synchronized (mLock) {
        addCallbacks(callbacks);
        return startLoader(new Callbacks[] { callbacks });
    }
}
private boolean startLoader(@NonNull final Callbacks[] newCallbacks) {
//省略部分代码
//调用新的执行之前会将老的停掉
                     stopLoader();
                mLoaderTask = new LoaderTask(
                        mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, loaderResults);
                MODEL_EXECUTOR.post(mLoaderTask);
                
                //省略部分代码
}
        为了避免重复执行代码,先 LoaderTask 继承了Runnable, 所以直接看run 方法。 允许我可耻的删除部分代码,我们只需要知道在该run 方法里面执行了5步
loadWorkspace加载workSpace数据,更新。loadAllApps加载所有app,更新。loadDeepShortcuts快捷方式,就是长按出来的那个小列表,更新。allWidgetsList加载小组件,更新。loadFolderNames加载文件夹,更新。
            
            
              java
              
              
            
          
             public void run() {
        synchronized (this) {
           //做了判断 如果stop没停止就不能开始
            if (mStopped) {
                return;
            }
        }
     
        try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
            List<ShortcutInfo> allShortcuts = new ArrayList<>();
          
            try {
                loadWorkspace(allShortcuts, memoryLogger);
            } finally {
                Trace.endSection();
            }
           
          //绑定
            mResults.bindWorkspace(true /* incrementBindId */);
            logASplit(logger, "bindWorkspace");
          //完成workSpace
            mModelDelegate.workspaceLoadComplete();
         
            // second step
            
            List<LauncherActivityInfo> allActivityList;
            try {
               allActivityList = loadAllApps();
            } finally {
                Trace.endSection();
            }
             //
            mResults.bindAllApps();
            logASplit(logger, "bindAllApps");
             
          //更新icon
            updateHandler.updateIcons(allActivityList,
                    LauncherActivityCachingLogic.newInstance(mApp.getContext()),
                    mApp.getModel()::onPackageIconsUpdated);
        
       
    
            // third step
            List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
        
            verifyNotStopped();
            mResults.bindDeepShortcuts();
          
            updateHandler.updateIcons(allDeepShortcuts,
                    new ShortcutCachingLogic(), (pkgs, user) -> { });
            // Take a break
        
            // fourth step
            List<ComponentWithLabelAndIcon> allWidgetsList =
                    mBgDataModel.widgetsModel.update(mApp, null);
           
            mResults.bindWidgets();
          
           
            updateHandler.updateIcons(allWidgetsList,
                    new ComponentWithIconCachingLogic(mApp.getContext(), true),
                    mApp.getModel()::onWidgetLabelsUpdated);
           
            // fifth step
            loadFolderNames();
            verifyNotStopped();
            updateHandler.finish();
            logASplit(logger, "finish icon update");
            mModelDelegate.modelLoadComplete();
            transaction.commit();
          
        } 
        注意在每个加载完成的时候都会调用一下对应的mResults.doxxxx(); 我很好奇bindAllApps 干了啥
            
            
              java
              
              
            
          
          public void bindAllApps() {
    // shallow copy
    AppInfo[] apps = mBgAllAppsList.copyData();
    int flags = mBgAllAppsList.getFlags();
    executeCallbacksTask(c -> c.bindAllApplications(apps, flags), mUiExecutor);
}
protected void executeCallbacksTask(CallbackTask task, Executor executor) {
    executor.execute(() -> {
        if (mMyBindingId != mBgDataModel.lastBindId) {
            Log.d(TAG, "Too many consecutive reloads, skipping obsolete data-bind");
            return;
        }
        for (Callbacks cb : mCallbacksList) {
            task.execute(cb);
        }
    });
}
        okok,我们从上面代码知道Launcher 的oncreart() 方法里面把this 传给了LaucherMode,然后传给了LoaderResult,给到了作为参数构建了LoaderTask。 所以这里其实会回调回Launcher的bindAllApplications
            
            
              java
              
              
            
          
          @TargetApi(Build.VERSION_CODES.S)
public void bindAllApplications(AppInfo[] apps, int flags) {
    mAppsView.getAppsStore().setApps(apps, flags);
    PopupContainerWithArrow.dismissInvalidPopup(this);
    if (Utilities.ATLEAST_S) {
        Trace.endAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
                DISPLAY_ALL_APPS_TRACE_COOKIE);
    }
}
        同样bindWorkspace 回调 bindStringCache 方法,大家感兴趣可以看下其他方法。