summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/allapps/AlphabeticalAppsList.java')
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java93
1 files changed, 67 insertions, 26 deletions
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 608e898ae..5e7a5cac5 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -298,35 +298,89 @@ public class AlphabeticalAppsList {
updateAdapterItems();
}
+ private List<AppInfo> processPredictedAppComponents(List<ComponentKey> components) {
+ if (mComponentToAppMap.isEmpty()) {
+ // Apps have not been bound yet.
+ return Collections.emptyList();
+ }
+
+ List<AppInfo> predictedApps = new ArrayList<>();
+ for (ComponentKey ck : components) {
+ AppInfo info = mComponentToAppMap.get(ck);
+ if (info != null) {
+ predictedApps.add(info);
+ } else {
+ if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ Log.e(TAG, "Predicted app not found: " + ck);
+ }
+ }
+ // Stop at the number of predicted apps
+ if (predictedApps.size() == mNumPredictedAppsPerRow) {
+ break;
+ }
+ }
+ return predictedApps;
+ }
+
/**
- * Sets the current set of predicted apps. Since this can be called before we get the full set
- * of applications, we should merge the results only in onAppsUpdated() which is idempotent.
+ * Sets the current set of predicted apps.
+ *
+ * This can be called before we get the full set of applications, we should merge the results
+ * only in onAppsUpdated() which is idempotent.
+ *
+ * If the number of predicted apps is the same as the previous list of predicted apps,
+ * we can optimize by swapping them in place.
*/
public void setPredictedApps(List<ComponentKey> apps) {
mPredictedAppComponents.clear();
mPredictedAppComponents.addAll(apps);
- onAppsUpdated();
+
+ List<AppInfo> newPredictedApps = processPredictedAppComponents(apps);
+ // We only need to do work if any of the visible predicted apps have changed.
+ if (!newPredictedApps.equals(mPredictedApps)) {
+ if (newPredictedApps.size() == mPredictedApps.size()) {
+ swapInNewPredictedApps(newPredictedApps);
+ } else {
+ // We need to update the appIndex of all the items.
+ onAppsUpdated();
+ }
+ }
}
/**
- * Sets the current set of apps.
+ * Swaps out the old predicted apps with the new predicted apps, in place. This optimization
+ * allows us to skip an entire relayout that would otherwise be called by notifyDataSetChanged.
+ *
+ * Note: This should only be called if the # of predicted apps is the same.
+ * This method assumes that predicted apps are the first items in the adapter.
*/
- public void setApps(List<AppInfo> apps) {
- mComponentToAppMap.clear();
- addApps(apps);
+ private void swapInNewPredictedApps(List<AppInfo> apps) {
+ mPredictedApps.clear();
+ mPredictedApps.addAll(apps);
+
+ int size = apps.size();
+ for (int i = 0; i < size; ++i) {
+ AppInfo info = apps.get(i);
+ AdapterItem appItem = AdapterItem.asPredictedApp(i, "", info, i);
+ appItem.rowAppIndex = i;
+ mAdapterItems.set(i, appItem);
+ mFilteredApps.set(i, info);
+ mAdapter.notifyItemChanged(i);
+ }
}
/**
- * Adds new apps to the list.
+ * Sets the current set of apps.
*/
- public void addApps(List<AppInfo> apps) {
- updateApps(apps);
+ public void setApps(List<AppInfo> apps) {
+ mComponentToAppMap.clear();
+ addOrUpdateApps(apps);
}
/**
- * Updates existing apps in the list
+ * Adds or updates existing apps in the list
*/
- public void updateApps(List<AppInfo> apps) {
+ public void addOrUpdateApps(List<AppInfo> apps) {
for (AppInfo app : apps) {
mComponentToAppMap.put(app.toComponentKey(), app);
}
@@ -432,20 +486,7 @@ public class AlphabeticalAppsList {
// Process the predicted app components
mPredictedApps.clear();
if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) {
- for (ComponentKey ck : mPredictedAppComponents) {
- AppInfo info = mComponentToAppMap.get(ck);
- if (info != null) {
- mPredictedApps.add(info);
- } else {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
- Log.e(TAG, "Predicted app not found: " + ck);
- }
- }
- // Stop at the number of predicted apps
- if (mPredictedApps.size() == mNumPredictedAppsPerRow) {
- break;
- }
- }
+ mPredictedApps.addAll(processPredictedAppComponents(mPredictedAppComponents));
if (!mPredictedApps.isEmpty()) {
// Add a section for the predictions