Launcer作为一个独立的APP,从开始执行到加载完成的整个流程。

启动核心代码如下:

/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

@Override    protected void onCreate(Bundle savedInstanceState) {        Log.d(TAG,"onCreate =======");               ....              mModel = app.setLauncher(this);        initDeviceProfile(app.getInvariantDeviceProfile());        mSharedPrefs = Utilities.getPrefs(this);        mIconCache = app.getIconCache();        mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);        mDragController = new DragController(this);        mAllAppsController = new AllAppsTransitionController(this);        mStateManager = new LauncherStateManager(this);        UiFactory.onCreate(this);        mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);        mAppWidgetHost = new LauncherAppWidgetHost(this);        mAppWidgetHost.startListening();        mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null);          ...        setupViews();        ...      int currentScreen = PagedView.INVALID_RESTORE_PAGE;        if (savedInstanceState != null) {            currentScreen = savedInstanceState.getInt(RUNTIME_STATE_CURRENT_SCREEN, currentScreen);        }        Log.e(TAG,"currentScreen :"+currentScreen+","+", loader bind: "+mModel.startLoader(currentScreen)+", internalStateHandled: "+internalStateHandled);        if (!mModel.startLoader(currentScreen)) {            if (!internalStateHandled) {                // If we are not binding synchronously, show a fade in animation when                // the first page bind completes.                mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);            }        } else {            // Pages bound synchronously.            mWorkspace.setCurrentPage(currentScreen);            setWorkspaceLoading(true);        }        ...    }

其中,setupViews,查找所有的view,并配置,

private void setupViews() {         ...        // default state, otherwise we will update to the wrong offsets in RTL        mWorkspace.lockWallpaperToDefaultPage();        mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */);        mDragController.addDragListener(mWorkspace);        // Get the search/delete/uninstall bar        mDropTargetBar = mDragLayer.findViewById(R.id.drop_target_bar);        // Setup Apps        mAppsView = findViewById(R.id.apps_view);        // Setup the drag controller (drop targets have to be added in reverse order in priority)        mDragController.setMoveTarget(mWorkspace);        mDropTargetBar.setup(mDragController);        mAllAppsController.setupViews(mAppsView);    }
1、packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.java
 LauncherModel setLauncher(Launcher launcher) {        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);        mModel.initialize(launcher);        return mModel;    }
2、/packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java

其中 Launcer 实现了 Callbacks 接口,

 public void initialize(Callbacks callbacks) {        synchronized (mLock) {            Preconditions.assertUIThread();            mCallbacks = new WeakReference<>(callbacks);        }    }
3、/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
 initDeviceProfile(app.getInvariantDeviceProfile());
4、/packages/apps/Launcher3/src/com/android/launcher3/LauncherAppWidgetHost.java
  @Override    public void startListening() {               ...        try {            super.startListening();        } catch (Exception e) {            if (!Utilities.isBinderSizeError(e)) {                throw new RuntimeException(e);            }            // We're willing to let this slide. The exception is being caused by the list of            // RemoteViews which is being passed back. The startListening relationship will            // have been established by this point, and we will end up populating the            // widgets upon bind anyway. See issue 14255011 for more context.        }        // We go in reverse order and inflate any deferred widget        for (int i = mViews.size() - 1; i >= 0; i--) {            LauncherAppWidgetHostView view = mViews.valueAt(i);            if (view instanceof DeferredAppWidgetHostView) {                view.reInflate();            }        }    }
5-6、 /packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
 private void setupViews() {              ...        mWorkspace = mDragLayer.findViewById(R.id.workspace);        mWorkspace.initParentViews(mDragLayer);        mOverviewPanel = findViewById(R.id.overview_panel);        mOverviewPanelContainer = findViewById(R.id.overview_panel_container);        mHotseat = findViewById(R.id.hotseat);        mHotseatSearchBox = findViewById(R.id.search_container_hotseat);                   ...        mWorkspace.setup(mDragController);        // Until the workspace is bound, ensure that we keep the wallpaper offset locked to the        // default state, otherwise we will update to the wrong offsets in RTL        mWorkspace.lockWallpaperToDefaultPage();        mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */);               ...    }
7-8、/packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java
  public boolean startLoader(int synchronousBindPage) {        // Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems        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            if (mCallbacks != null && mCallbacks.get() != null) {                                ...                if (mModelLoaded && !mIsLoaderTaskRunning) {                    // Divide the set of loaded items into those that we are binding synchronously,                    // and everything else that is to be bound normally (asynchronously).                    loaderResults.bindWorkspace();                    // For now, continue posting the binding of AllApps as there are other                    // issues that arise from that.                    loaderResults.bindAllApps();                    loaderResults.bindDeepShortcuts();                    loaderResults.bindWidgets();                    return true;                } else {                    startLoaderForResults(loaderResults);                }            }        }        return false;    } public void startLoaderForResults(LoaderResults results) {        synchronized (mLock) {            stopLoader();            mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);            runOnWorkerThread(mLoaderTask);        }    }
9-14 /packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java
         ...       TraceHelper.beginSection(TAG);        try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {            TraceHelper.partitionSection(TAG, "step 1.1: loading workspace");            loadWorkspace();            verifyNotStopped();            TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace");            mResults.bindWorkspace();            // Notify the installer packages of packages with active installs on the first screen.            TraceHelper.partitionSection(TAG, "step 1.3: send first screen broadcast");            sendFirstScreenActiveInstallsBroadcast();            // Take a break            TraceHelper.partitionSection(TAG, "step 1 completed, wait for idle");            waitForIdle();            verifyNotStopped();            // second step            TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");            loadAllApps();            TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");            verifyNotStopped();            mResults.bindAllApps();            verifyNotStopped();            TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache");            updateIconCache();            // Take a break            TraceHelper.partitionSection(TAG, "step 2 completed, wait for idle");            waitForIdle();            verifyNotStopped();            // third step   /home/meng/apinext_workspace            TraceHelper.partitionSection(TAG, "step 3.1: loading deep shortcuts");            loadDeepShortcuts();            verifyNotStopped();            TraceHelper.partitionSection(TAG, "step 3.2: bind deep shortcuts");            mResults.bindDeepShortcuts();            // Take a break            TraceHelper.partitionSection(TAG, "step 3 completed, wait for idle");            waitForIdle();            verifyNotStopped();            // fourth step            TraceHelper.partitionSection(TAG, "step 4.1: loading widgets");            mBgDataModel.widgetsModel.update(mApp, null);            verifyNotStopped();            TraceHelper.partitionSection(TAG, "step 4.2: Binding widgets");            mResults.bindWidgets();            transaction.commit();        } catch (CancellationException e) {            // Loader stopped, ignore            TraceHelper.partitionSection(TAG, "Cancelled");        }        TraceHelper.endSection(TAG);      ...

加载完成,会跳转到LoaderResults,进行绑定操作,
通过接口Callbacks 回调,返回Launcher。

    public void bindWorkspace() {        Runnable r;        Callbacks callbacks = mCallbacks.get();        // Don't use these two variables in any of the callback runnables.        // Otherwise we hold a reference to them.        if (callbacks == null) {            // This launcher has exited and nobody bothered to tell us.  Just bail.            Log.w(TAG, "LoaderTask running with no launcher");            return;        }        // Save a copy of all the bg-thread collections        ArrayList workspaceItems = new ArrayList<>();        ArrayList appWidgets = new ArrayList<>();        final ArrayList orderedScreenIds = new ArrayList<>();        synchronized (mBgDataModel) {            workspaceItems.addAll(mBgDataModel.workspaceItems);            appWidgets.addAll(mBgDataModel.appWidgets);            orderedScreenIds.addAll(mBgDataModel.workspaceScreens);            mBgDataModel.lastBindId++;        }        final int currentScreen;        {            int currScreen = mPageToBindFirst != PagedView.INVALID_RESTORE_PAGE                    ? mPageToBindFirst : callbacks.getCurrentWorkspaceScreen();            if (currScreen >= orderedScreenIds.size()) {                // There may be no workspace screens (just hotseat items and an empty page).                currScreen = PagedView.INVALID_RESTORE_PAGE;            }            currentScreen = currScreen;        }        final boolean validFirstPage = currentScreen >= 0;        final long currentScreenId =                validFirstPage ? orderedScreenIds.get(currentScreen) : INVALID_SCREEN_ID;        // Separate the items that are on the current screen, and all the other remaining items        ArrayList currentWorkspaceItems = new ArrayList<>();        ArrayList otherWorkspaceItems = new ArrayList<>();        ArrayList currentAppWidgets = new ArrayList<>();        ArrayList otherAppWidgets = new ArrayList<>();        filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,                otherWorkspaceItems);        filterCurrentWorkspaceItems(currentScreenId, appWidgets, currentAppWidgets,                otherAppWidgets);        sortWorkspaceItemsSpatially(currentWorkspaceItems);        sortWorkspaceItemsSpatially(otherWorkspaceItems);        // Tell the workspace that we're about to start binding items        r = new Runnable() {            public void run() {                Callbacks callbacks = mCallbacks.get();                if (callbacks != null) {                    callbacks.clearPendingBinds();                    callbacks.startBinding();                }            }        };        mUiExecutor.execute(r);        // Bind workspace screens        mUiExecutor.execute(new Runnable() {            @Override            public void run() {                Callbacks callbacks = mCallbacks.get();                if (callbacks != null) {                    callbacks.bindScreens(orderedScreenIds);                }            }        });        Executor mainExecutor = mUiExecutor;        // Load items on the current page.        bindWorkspaceItems(currentWorkspaceItems, currentAppWidgets, mainExecutor);        // In case of validFirstPage, only bind the first screen, and defer binding the        // remaining screens after first onDraw (and an optional the fade animation whichever        // happens later).        // This ensures that the first screen is immediately visible (eg. during rotation)        // In case of !validFirstPage, bind all pages one after other.        final Executor deferredExecutor =                validFirstPage ? new ViewOnDrawExecutor() : mainExecutor;        mainExecutor.execute(new Runnable() {            @Override            public void run() {                Callbacks callbacks = mCallbacks.get();                if (callbacks != null) {                    callbacks.finishFirstPageBind(                            validFirstPage ? (ViewOnDrawExecutor) deferredExecutor : null);                }            }        });        bindWorkspaceItems(otherWorkspaceItems, otherAppWidgets, deferredExecutor);        // Tell the workspace that we're done binding items        r = new Runnable() {            public void run() {                Callbacks callbacks = mCallbacks.get();                if (callbacks != null) {                    callbacks.finishBindingItems();                }            }        };        deferredExecutor.execute(r);        if (validFirstPage) {            r = new Runnable() {                public void run() {                    Callbacks callbacks = mCallbacks.get();                    if (callbacks != null) {                        // We are loading synchronously, which means, some of the pages will be                        // bound after first draw. Inform the callbacks that page binding is                        // not complete, and schedule the remaining pages.                        if (currentScreen != PagedView.INVALID_RESTORE_PAGE) {                            callbacks.onPageBoundSynchronously(currentScreen);                        }                        callbacks.executeOnNextDraw((ViewOnDrawExecutor) deferredExecutor);                    }                }            };            mUiExecutor.execute(r);        }    }

11.2、bindAllApplications
13.2、bindDeepShortcuts
14.2、bindWidgets
处理逻辑类似,在此就不贴代码了。

有点不同是是loading widgets,图中的14.1、update(mApp, null)。
加载逻辑在这个文件,
/packages/apps/Launcher3/src/com/android/launcher3/model/WidgetsModel.java。

加载完成后,执行 transaction.commit()
在/packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.jav

 public void commit() {            synchronized (mLock) {                // Everything loaded bind the data.                mModelLoaded = true;            }        }

然后,Launcher将数据赋值给各种View。

总结:

  启动Launcher后,通过LauncherModel控制加载逻辑,LoaderTask开启线程加载数据,LoaderResults进行数据绑定的处理,最后将数据返回给Launcher处理。

更多相关文章

  1. 【Android学习系列】android Content Provider 应用步骤
  2. Android(安卓)intent数据传递
  3. android百度地图(二)之定位
  4. Android中的数据库——SQLite
  5. 解决 pinyin4j 在Android(安卓)某些编译环境下不能用
  6. Sqlite3 增删改查操作实例
  7. Android(安卓)ListView实现通讯录的例子
  8. Android学习笔记_31_通过后台代码生成View对象以及动态加载XML布
  9. Android(安卓)MediaPlayer播放prepareAsync called in state 8解

随机推荐

  1. android 获取手机的信息
  2. android之接收和发送广播的开机可自动运
  3. Android通知的基本用法
  4. android获取wifi信号强度
  5. Android ScrollView 内部控件 layout_mar
  6. android button 上添加图片
  7. [置顶] Android高手进阶教程(四)之----An
  8. android 自动化(1)
  9. 解决java.lang.RuntimeException: Unable
  10. Fiddler跟踪监控android数据包