在數據從數據庫加載到內存之後,接下來的工作就是把這些數據與launcher的UI視圖綁定。綁定的過程在LauncherModel.bindWorkspace()方法中完成,在這個方法中會調用回調接口Callback裏相應的回調方法。
Callback接口的定義如下:
public interface Callbacks {
public boolean setLoadOnResume();
public int getCurrentWorkspaceScreen();
public void startBinding();
public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end,
boolean forceAnimateIcons);
public void bindScreens(ArrayList<Long> orderedScreenIds);
public void bindAddScreens(ArrayList<Long> orderedScreenIds);
public void bindFolders(HashMap<Long,FolderInfo> folders);
public void finishBindingItems(boolean upgradePath);
public void bindAppWidget(LauncherAppWidgetInfo info);
public void bindAllApplications(ArrayList<AppInfo> apps);
public void bindAppsAdded(ArrayList<Long> newScreens,
ArrayList<ItemInfo> addNotAnimated,
ArrayList<ItemInfo> addAnimated,
ArrayList<AppInfo> addedApps);
public void bindAppsUpdated(ArrayList<AppInfo> apps);
public void bindComponentsRemoved(ArrayList<String> packageNames,
ArrayList<AppInfo> appInfos,
boolean matchPackageNamesOnly);
public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
public void bindSearchablesChanged();
public boolean isAllAppsButtonRank(int rank);
public void onPageBoundSynchronously(int page);
public void dumpLogsToLocalData();
}
通過方法名我們大概可以猜到每個回調方法的作用,因爲Launcher類(Main Activity)實現了該接口,並作爲參數傳遞給了LauncherModel的mCallback,所以bindWorkspace的過程就是通過回調,一步步地通知Launcher類進行相應界面和相應數據的綁定。
bindWorkspace的過程如下:
1.將items分爲current和other
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, MAIN_THREAD_BINDING_RUNNABLE);
完成綁定前的初始化工作。
3.調用bindScreens()
final Runnable r = new Runnable() {
@Override
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
callbacks.bindScreens(orderedScreens);
}
}
};
runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
完成screen的初始化。
4.加載當前頁面的item
bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
currentFolders, null);
bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,
(isLoadingSynchronously ? mDeferredBindRunnables : null));
6.調用finishBindingItems()
// Tell the workspace that we're done binding items
r = new Runnable() {
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
callbacks.finishBindingItems(isUpgradePath);
}
mIsLoadingAndBindingWorkspace = false;
}
};
runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
以上是Workspace數據綁定的步驟,Launcher類通過回調在每個步驟中完成相應的UI渲染工作。