android 启动器开发,Android启动器(Launcher)开发详解
目錄
[隱藏]
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
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
[編輯]166085
Launcher: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,導致沒有將未接來電的圖標進行更新。
總結
以上是生活随笔為你收集整理的android 启动器开发,Android启动器(Launcher)开发详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 玉米加农炮怎么用 玉米的适用人群
- 下一篇: 旅行青蛙三种死亡结局 旅行的意义是什么