上一章咱們講了Launcher的數據加載,包括:默認配置應用、文件夾以及widget的加載,全部應用的加載以及全部Widget的加載,數據加載完成後開始分批進行繪製到桌面上,包含默認配置bind,全部應用bind,全部小部件bind。下面我就從這幾個方面進行分析,看看他們的加載過程。java
上一章講到默認配置加載的位置:git
private void loadAndBindWorkspace() {
...
if (!mWorkspaceLoaded) {
loadWorkspace();
...
}
// Bind the workspace
bindWorkspace(-1);
}
複製代碼
這裏主要是加載默認配置,而後調用bindWorkspace進行綁定,咱們先看一下流程圖:github
整個流程看似東西不少,其實就是準備數據,而後開始綁定,下面咱們看bindWorkspace的主要代碼:數據庫
private void bindWorkspace(int synchronizeBindPage) {
//準備參數
...
//開始綁定
...
bindWorkspaceScreens(oldCallbacks, orderedScreenIds);
// Load items on the current page
bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
currentFolders, null);
...
bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,
(isLoadingSynchronously ? mDeferredBindRunnables : null));
//結束綁定
...
}
複製代碼
咱們先分析第一個方法:bindWorkspaceScreens,咱們知道桌面上的圖標、文件夾等是放置到CellLayout(實際內部還有一個容器)中的,所以咱們要首先添加CellLayout整個容器, 也就是這個方法,代碼:ide
private void bindWorkspaceScreens(final Callbacks oldCallbacks, final ArrayList<Long> orderedScreens) {
final Runnable r = new Runnable() {
@Override
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
callbacks.bindScreens(orderedScreens);
}
}
};
runOnMainThread(r);
}
複製代碼
代碼很簡單,就是調用回調函數callbacks.bindScreens,這個回調函數是在Launcher中實現的,所以咱們看流程圖:函數
代碼實現就是在bindAddScreens方法中經過for循環添加CellLayout,比較簡單再也不貼代碼。post
咱們接着看第二第三個函數,這兩個函數是同樣的,可是參數不同,從參數名字能夠看到第一個bind當前頁面的圖標、文件夾、widget的,第二個是bind其餘屏幕圖標、文件夾、widget的,所以咱們只講一個流程,剩下的是同樣的。this
咱們先看流程圖:spa
從流程圖看其實就是三個for循環,分別綁定圖標、文件夾、小部件,code
public void bindItems(final ArrayList<ItemInfo> shortcuts, final int start, final int end, final boolean forceAnimateIcons) {
...
for (int i = start; i < end; i++) {
final ItemInfo item = shortcuts.get(i);
// 若是是在Hotseat中而且沒有Hotseat則跳過繼續
if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
mHotseat == null) {
continue;
}
final View view;
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
ShortcutInfo info = (ShortcutInfo) item;
view = createShortcut(info);
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
(FolderInfo) item, mIconCache);
break;
default:
throw new RuntimeException("Invalid Item Type");
}
workspace.addInScreenFromBind(view, item.container, item.screenId, item.cellX,
item.cellY, 1, 1);
}
複製代碼
在上面的switch語句中判斷Item的類型,根據不一樣類型來生成不一樣的View,最後經過workspace.addInScreenFromBind方法將view綁定到桌面上,咱們接着看一下addInScreenFromBind這個方法,這個方法最後調用到Workspace中的addInScreen方法,在這個方法中有兩個參數spanX、spanY沒有講過,我來解釋一下,咱們第一章講了圖標排列到桌面上是按照4x4後者4x5等形式,那麼每一個單元是一個圖標位置,可是,小部件的佔用不僅是一個圖標,有可能幾個圖標的位置,而spanX就是橫向佔用的單元格個數,相應的spanY就是Y方向的佔用個數。根據控件的起始位置,以及佔用單元格個數就能夠肯定他在桌面上的位置。addInScreen代碼我就不貼了,我只是在這說一下過程,進入這個方法,首先判斷container的類型,也就是父容器的類型:CellLayout仍是Hotseat,而後判斷是文件夾仍是圖標,最後經過調用layout.addViewToCellLayout方法根據相應的參數來添加到相應的容器裏面。
其餘兩個的綁定也是差很少的,只是widget的相對複雜一點,這裏再也不講解,後面我會單獨寫一章來說解widget的加載添加。
綁定全部應用實際上是綁定二級界面的全部應用圖標,代碼開始位置是:LauncherModel中的loadAllApps方法,首先加載手機裏的全部應用信息,而後生成對應的對象,最後經過調用callbacks.bindAllApplications方法將全部應用綁定到二級界面,回調函數依然是在Launcher中實現,二級界面是AllAppsContainerView,根據代碼流程調用onAppsUpdated方法,在這個方法中排序最後調用updateAdapterItems方法,這個界面是一個RecyclerView,準備好數據庫,刷新適配器便可。
綁定Widget也是從loadAllApps這個方法開始的,在這個方法的最後面有個loadAndBindWidgetsAndShortcuts,經過這個方法綁定快捷方式和widget到小部件界面,看代碼:
public void loadAndBindWidgetsAndShortcuts(final Callbacks callbacks, final boolean refresh) {
runOnWorkerThread(new Runnable() {
@Override
public void run() {
updateWidgetsModel(refresh);
final WidgetsModel model = mBgWidgetsModel.clone();
mHandler.post(new Runnable() {
@Override
public void run() {
Callbacks cb = getCallback();
if (callbacks == cb && cb != null) {
callbacks.bindAllPackages(model);
}
}
});
// update the Widget entries inside DB on the worker thread.
LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
model.getRawList());
}
});
}
複製代碼
首先調用updateWidgetsModel方法,
void updateWidgetsModel(boolean refresh) {
PackageManager packageManager = mApp.getContext().getPackageManager();
final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
widgetsAndShortcuts.addAll(getWidgetProviders(mApp.getContext(), refresh));
Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts);
}
複製代碼
在這個方法中首先調用getWidgetProviders方法來加載全部的小部件信息,而後經過packageManager.queryIntentActivities方法加載全部的快捷方式信息,最後將全部的信息放置到WidgetsModel中,完成後經過調用callbacks.bindAllPackages回調函數開始綁定全部的小部件和快捷方式,回調函數在Launcher中實現,而後調用WidgetsContainerView中的addWidgets方法傳入WidgetsModel對象,而後經過調用刷新適配器來刷新小部件界面。
最後:這一章相對簡單,主要是UI的繪製,有一些流程我沒有講,主要是UI繪製其實和自定義view相關,不少人一看就會了,因此再也不講解,不會的能夠去看看源碼。
Github地址:github.com/yuchuangu85…