Android啟動器(Launcher)開發詳解

來源:互聯網
上載者:User

第1章  Launcher的誕生

1.1 Framework啟動Launcher流程
      

 


1.2 Launcher自身啟動流程
App-Launcher-資料載入和UI綁定
目錄 [隱藏]
1 1.Launcher案頭資料和主菜單資料載入流程
1.1 1.1 載入主菜單資料
1.1.1 1.載入調用流程
1.2 1.2 載入案頭資料
1.3 1.3 插入SIM卡時候的資料載入的問題
1.4 1.4 經典Bug
1.4.1 166085
 
[編輯]1.Launcher案頭資料和主菜單資料載入流程[編輯]1.1 載入主菜單資料PackageManager中載入應用程式資料結構,AppwidgetsManager中載入小組件資料結構,從Favorites資料庫中載入案頭資料結構

 
 

[編輯]1.載入調用流程LoaderTask一個任務是載入案頭,一個任務是載入抽屜,同步(一個接一個)進行。LauncherModel:waitForIdle()方法用於等待案頭載入完成再載入抽屜。
等待從favorite表中loadAndBindWorkspace的完成,即完成 案頭的資料 從資料庫到記憶體對象的載入,並且已經顯示到了案頭Workspace,
然後開始loadAndBindAllApps載入主菜單的資料(PackageManager) ,在launcher-loader 子線程擷取資料後通過mHandler.postIdle() mHandler.post()將任務post到主線程任務隊列DefferedHandler:mQueue中更新UI。


/** Runs the specified runnable immediately if called from the main thread, otherwise it is
    * posted on the main thread handler. */
   private void runOnMainThread(Runnable r) {
       if (sWorkerThread.getThreadId() == Process.myTid()) {
           // If we are on the worker thread, post onto the main handler
           mHandler.post(r);
       } else {
           r.run();
       }
   }
/** Runs the specified runnable immediately if called from the worker thread, otherwise it is
    * posted on the worker thread handler. */
   private static void runOnWorkerThread(Runnable r) {
       if (sWorkerThread.getThreadId() == Process.myTid()) {
           r.run();
       } else {
           // If we are not on the worker thread, then post to the worker handler
           sWorker.post(r);
       }
   }
當使用者點擊主功能表按鈕的時候,將loadAllAppsByBatch獲得的資料與PagedViewIcon綁定。 AppsCustomizePagedView:syncAppsPageItems將ApplicationInfo數組構建每一個 PagedViewIcon並添加到PagedViewCellLayout。


       for (int i = startIndex; i < endIndex; ++i) {
           ApplicationInfo info = mApps.get(i);
           PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
                   R.layout.apps_customize_application, layout, false);
           icon.applyFromApplicationInfo(info, true, this);
           pagedViewCellLayout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
           items.add(info);
           images.add(info.iconBitmap);
       }
LoaderTask:run()--->LoaderTask:loadAndBindAllApps()--->LoaderTask:loadAllAppsByBatch()--->
Launcher:bindAllApplications()--->AppsCustomizePagedView:setApps()--->AppsCustomizePagedView:invalidateOnDataChange()

 

 
 

在點擊“主菜單”按鈕之前, AppsCustomizePagedView沒有任何 Child.點擊之後執行時序如下: AppsCustomizeTabHost.onMeasure(...)--->AppsCustomizePagedView.onMeasure(...)--->AppsCustomizePagedView.onDataReady(...)--->(AppsCustomizePagedView)PagedView.invalidatePageData--->AppsCustomizePagedView:syncPages()

[編輯]1.2 載入案頭資料LauncherModel:startLoader--->LoaderTask:bindWorkspace--->LoaderTask:bindWorkspaceItems--->Launcher:bindItems

 
 

[編輯]1.3 插入SIM卡時候的資料載入的問題1.Launcher因為低記憶體會導致Launcher Activtiy 執行onDestory() onCreate(),會再次執行


startLoader-->loadAndBindWorkSpace---->loadAndBindAllApps

2.Launcher 註冊了act=android.intent.action.CONFIGURATION_CHANGED Reload apps on config change. curr_mcc:460 prevmcc:0 當識別SIM 的時候也會執行

startLoader-->loadAndBindWorkSpace---->loadAndBindAllApps
但是這兩種情況導致startLoader調用的時候mAllAppsLoaded==false,mWorkspaceLoaded==false 所以其實是在執行如下,不會重新載入資料結構ArrayList<ApplicationInfo>

startLoader-->BindWorkSpace---->onlyBindAllApps

--------------------------------------------------------------------------------

private void loadAndBindAllApps() {
           if (DEBUG_LOADERS) {
               Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
           }
           if (!mAllAppsLoaded) {
            loadAllAppsFromPersistence();
               loadAllAppsByBatch();
               synchronized (LoaderTask.this) {
                   if (mStopped) {
                       return;
                   }
                   mAllAppsLoaded = true;
               }
           } else {
               onlyBindAllApps();
           }
       }

--------------------------------------------------------------------------------
[編輯]1.4 經典Bug[編輯]166085Launcher:onCreate()---new Thread--->startLoader--->讀favoriteDB--->post(bindItem)
|
Launcher:onReume()----new Thread--->getMissedCallCount--->post(updateCallLogIcon)------>workspace:updateShortCut()

當來電 啟動 InCallScreen 的時候 會執行Launher:onDestory,掛了電話會執行Launcher:onCreate 由於startLoader消耗的時間 要比getMissedCallCount 長,導致post(updateCallLogIcon)先被執行, 可是這個時候案頭的表徵圖沒有被bind,導致沒有將未接來電的表徵圖進行更新。

 

 

第2章 Launcher布局與視圖
2.1 hierarchyviewer研究launcher.xml布局

 在Android的SDK工具包中,有很多十分有用的工具,可以協助程式員開發與測試Android應用程式,大大提高其工作效率。其中的一款叫Hierachy Viewer的可視化調試工具,可以很方便地在開發人員設計,調試和調整介面時,提高使用者的開發效率。

第3章  Launcher View拖拽詳解

第4章  Launcher AppWiget架構

第5章  案頭縮圖實現

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.