Android Launcher源碼研究(二) 載入app流程1

來源:互聯網
上載者:User

標籤:android   launcher   源碼   

今天主要分析Android Launcher源碼中的一些重要類之間的關係,基本的載入流程。先來看一個類圖



  Launcher.java 是主Activity 在onCreate方法裡面初始化了LauncherMode執行個體.


LauncherApplication app = ((LauncherApplication)getApplication());

mModel = app.setLauncher(this);

直接進入LauncherApplication.java的方法 

    LauncherModel setLauncher(Launcher launcher) {        mModel.initialize(launcher);        return mModel;    }

這裡的mModel就是LauncherModel類了,LauncherModel扮演者重要的角色,實際上是個廣播,監控app的安裝,改變,和卸載另外就是載入所有app資訊

這裡Launcher實現了Callbacks介面,直接加入到callbacks列表中,後面的很多功能都要靠它回調處理

    public void initialize(Callbacks callbacks) {        synchronized (mLock) {            mCallbacks = new WeakReference<Callbacks>(callbacks);        }    }


在Launcher.java  onCreate的代碼中看下面的一段代碼.

        if (!mRestoring) {            if (sPausedFromUserAction) {                // If the user leaves launcher, then we should just load items asynchronously when                // they return.                mModel.startLoader(true, -1);            } else {                // We only load the page synchronously if the user rotates (or triggers a                // configuration change) while launcher is in the foreground                mModel.startLoader(true, mWorkspace.getCurrentPage());            }        }

源碼中注釋也顯示了2中情況,一種是目前使用者的介面不是案頭可能是某個應用程式介面 這樣我們通過後台非同步載入。

另外一種情況是 重新整理當前頁面的app資訊資料. 

現在定位到LauncherMode.java源碼中startLoader方法 部分代碼如下.

                if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) {                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);//同步載入當前頁                } else {                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);                    sWorker.post(mLoaderTask);//非同步載入                }
和上面講的一樣,載入當前頁面資訊還是更新所有資訊. synchronousBindPage就是目前使用者滑動到第幾個螢幕,一共是5個螢幕.

我們用到了LoaderTask這個類是一個Runnable實現.  這個地方用的是HandlerThread (這個類我以前沒用過,一直是自己擷取Looper再處理的 )

這個類就是具體載入appinfo,appwidget,  folder的資訊了。

我們看看LoaderTask run方法實現. 注意 LoaderTask 是LauncherMode的內部類.  

            keep_running: {                // Elevate priority when Home launches for the first time to avoid                // starving at boot time. Staring at a blank home is not cool.                synchronized (mLock) {                    if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +                            (mIsLaunching ? "DEFAULT" : "BACKGROUND"));                    android.os.Process.setThreadPriority(mIsLaunching                            ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);                }                if (loadWorkspaceFirst) {                    if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");                    loadAndBindWorkspace();//第一次載入                } else {                    if (DEBUG_LOADERS) Log.d(TAG, "step 1: special: loading all apps");                    loadAndBindAllApps(); //更新資料                }                if (mStopped) {                    break keep_running;                }                // Whew! Hard work done.  Slow us down, and wait until the UI thread has                // settled down.                synchronized (mLock) {                    if (mIsLaunching) {                        if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");                        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                    }                }                waitForIdle();                // second step                if (loadWorkspaceFirst) {                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");                    loadAndBindAllApps();                } else {                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");                    loadAndBindWorkspace();                }                // Restore the default thread priority after we are done loading items                synchronized (mLock) {                    android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);                }            }

按照源碼的注釋 是第一次載入workspace , 第二次載入所有的app 資訊,你會發現 loadAndBindAllApps方法和loadAndBindWorkspace 2次調用是倒著的。

我的理解就是  先執行載入workspace 再執行載入all apps.

我們定位到 loadAndBindWorkspace方法中,


   if (!mWorkspaceLoaded) {                loadWorkspace();                synchronized (LoaderTask.this) {                    if (mStopped) {                        return;                    }                    mWorkspaceLoaded = true;                }            }

如果workspace還沒載入就調用loadWorkspace方法. 定位到這個方法裡面,一目瞭然發現 都是直接擷取應用程式資訊了包括widget.

直接調用了 PackageManager,AppWidgetManager,ContentResolver 擷取資訊.

讀取資訊儲存後 我們需要與workspace匯合,這個地方是調用bindWorkspace

在這個方面裡面我們會發現使用前面說的callbacks進行回調完整資料與View的綁定顯示.

      /**         * Binds all loaded data to actual views on the main thread.         */        private void bindWorkspace(int synchronizeBindPage) {            final long t = SystemClock.uptimeMillis();            Runnable r;            // Don't use these two variables in any of the callback runnables.            // Otherwise we hold a reference to them.            final Callbacks oldCallbacks = mCallbacks.get();            if (oldCallbacks == null) {                // This launcher has exited and nobody bothered to tell us.  Just bail.                Log.w(TAG, "LoaderTask running with no launcher");                return;            }            final boolean isLoadingSynchronously = (synchronizeBindPage > -1);            final int currentScreen = isLoadingSynchronously ? synchronizeBindPage :                oldCallbacks.getCurrentWorkspaceScreen();            // Load all the items that are on the current page first (and in the process, unbind            // all the existing workspace items before we call startBinding() below.            unbindWorkspaceItemsOnMainThread();            ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();            ArrayList<LauncherAppWidgetInfo> appWidgets =                    new ArrayList<LauncherAppWidgetInfo>();            HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();            HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();            synchronized (sBgLock) {                workspaceItems.addAll(sBgWorkspaceItems);                appWidgets.addAll(sBgAppWidgets);                folders.putAll(sBgFolders);                itemsIdMap.putAll(sBgItemsIdMap);            }            ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();            ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();            ArrayList<LauncherAppWidgetInfo> currentAppWidgets =                    new ArrayList<LauncherAppWidgetInfo>();            ArrayList<LauncherAppWidgetInfo> otherAppWidgets =                    new ArrayList<LauncherAppWidgetInfo>();            HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();            HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();            // Separate the items that are on the current screen, and all the other remaining items            filterCurrentWorkspaceItems(currentScreen, workspaceItems, currentWorkspaceItems,                    otherWorkspaceItems);            filterCurrentAppWidgets(currentScreen, appWidgets, currentAppWidgets,                    otherAppWidgets);            filterCurrentFolders(currentScreen, itemsIdMap, folders, currentFolders,                    otherFolders);            sortWorkspaceItemsSpatially(currentWorkspaceItems);            sortWorkspaceItemsSpatially(otherWorkspaceItems);            // Tell the workspace that we're about to start binding items            r = new Runnable() {                public void run() {                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);                    if (callbacks != null) {                        callbacks.startBinding();                    }                }            };            runOnMainThread(r);            // Load items on the current page            bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,                    currentFolders, null);            if (isLoadingSynchronously) {                r = new Runnable() {                    public void run() {                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);                        if (callbacks != null) {                            callbacks.onPageBoundSynchronously(currentScreen);                        }                    }                };                runOnMainThread(r);            }            // Load all the remaining pages (if we are loading synchronously, we want to defer this            // work until after the first render)            mDeferredBindRunnables.clear();            bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,                    (isLoadingSynchronously ? mDeferredBindRunnables : null));            // Tell the workspace that we're done binding items            r = new Runnable() {                public void run() {                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);                    if (callbacks != null) {                        callbacks.finishBindingItems();                    }                    // If we're profiling, ensure this is the last thing in the queue.                    if (DEBUG_LOADERS) {                        Log.d(TAG, "bound workspace in "                            + (SystemClock.uptimeMillis()-t) + "ms");                    }                    mIsLoadingAndBindingWorkspace = false;                }            };            if (isLoadingSynchronously) {                mDeferredBindRunnables.add(r);            } else {                runOnMainThread(r);            }        }


這段代碼有很多需要解釋的,本質就是app,widgets, folders擷取並傳給主介面。今天就分析到這裡。後面還有很多,這次就分析到這裡,


如有問題 ,歡迎指出 謝謝。O(∩_∩)O~


 

Android Launcher源碼研究(二) 載入app流程1

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.