diff options
author | Winson Chung <winsonc@google.com> | 2015-05-20 16:07:46 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2015-05-21 20:33:01 +0000 |
commit | 3abcd5ba1ba0fe4d8061309dd073e36c64b05963 (patch) | |
tree | f2f3282de0847b3b8e69deb0e9791f59a7f7aa64 /src/com/android | |
parent | 324d78358c88d30eac587f4e1d679f9b5bf8d2f3 (diff) | |
download | android_packages_apps_Trebuchet-3abcd5ba1ba0fe4d8061309dd073e36c64b05963.tar.gz android_packages_apps_Trebuchet-3abcd5ba1ba0fe4d8061309dd073e36c64b05963.tar.bz2 android_packages_apps_Trebuchet-3abcd5ba1ba0fe4d8061309dd073e36c64b05963.zip |
Cleaning up some app model code.
- Preventing extra sorting when adding/updating apps
- Preventing extra logic when filtering apps
- Fixing overlapping prediction bar when all predictions are removed
- Fixing crash when retrieving section names for AppInfos whose titles
have been updated, but updateApps has not yet been called.
Change-Id: I1da468b0fd5c5cc404b6a5e6146a268fefeca267
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher3/AlphabeticalAppsList.java | 194 | ||||
-rw-r--r-- | src/com/android/launcher3/AppsContainerView.java | 4 |
2 files changed, 102 insertions, 96 deletions
diff --git a/src/com/android/launcher3/AlphabeticalAppsList.java b/src/com/android/launcher3/AlphabeticalAppsList.java index 82aaeb99a..5e05d11bc 100644 --- a/src/com/android/launcher3/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/AlphabeticalAppsList.java @@ -5,14 +5,10 @@ import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.Log; import com.android.launcher3.compat.AlphabeticIndexCompat; -import com.android.launcher3.compat.UserHandleCompat; -import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.model.AppNameComparator; -import java.text.Collator; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -121,10 +117,10 @@ public class AlphabeticalAppsList { } /** - * A callback to notify of changes to the filter. + * Callback to notify when the set of adapter items have changed. */ - public interface FilterChangedCallback { - void onFilterChanged(); + public interface AdapterChangedCallback { + void onAdapterItemsChanged(); } /** @@ -178,12 +174,20 @@ public class AlphabeticalAppsList { private static final int MAX_NUM_MERGES_PHONE = 2; private Context mContext; + + // The set of apps from the system not including predictions private List<AppInfo> mApps = new ArrayList<>(); + // The set of filtered apps with the current filter private List<AppInfo> mFilteredApps = new ArrayList<>(); - private List<AdapterItem> mSectionedFilteredApps = new ArrayList<>(); + // The current set of adapter items + private List<AdapterItem> mAdapterItems = new ArrayList<>(); + // The set of sections for the apps with the current filter private List<SectionInfo> mSections = new ArrayList<>(); + // The set of sections that we allow fast-scrolling to (includes non-merged sections) private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>(); + // The set of predicted app component names private List<ComponentName> mPredictedAppComponents = new ArrayList<>(); + // The set of predicted apps resolved from the component names and the current set of apps private List<AppInfo> mPredictedApps = new ArrayList<>(); private HashMap<CharSequence, String> mCachedSectionNames = new HashMap<>(); private RecyclerView.Adapter mAdapter; @@ -191,16 +195,16 @@ public class AlphabeticalAppsList { private AlphabeticIndexCompat mIndexer; private AppNameComparator mAppNameComparator; private MergeAlgorithm mMergeAlgorithm; - private FilterChangedCallback mFilterChangedCallback; + private AdapterChangedCallback mAdapterChangedCallback; private int mNumAppsPerRow; private int mNumPredictedAppsPerRow; - public AlphabeticalAppsList(Context context, FilterChangedCallback cb, int numAppsPerRow, + public AlphabeticalAppsList(Context context, AdapterChangedCallback auCb, int numAppsPerRow, int numPredictedAppsPerRow) { mContext = context; mIndexer = new AlphabeticIndexCompat(context); mAppNameComparator = new AppNameComparator(context); - mFilterChangedCallback = cb; + mAdapterChangedCallback = auCb; setNumAppsPerRow(numAppsPerRow, numPredictedAppsPerRow); } @@ -248,7 +252,7 @@ public class AlphabeticalAppsList { * Returns the current filtered list of applications broken down into their sections. */ public List<AdapterItem> getAdapterItems() { - return mSectionedFilteredApps; + return mAdapterItems; } /** @@ -278,11 +282,7 @@ public class AlphabeticalAppsList { public void setFilter(Filter f) { if (mFilter != f) { mFilter = f; - onAppsUpdated(); - mAdapter.notifyDataSetChanged(); - if (mFilterChangedCallback != null){ - mFilterChangedCallback.onFilterChanged(); - } + updateAdapterItems(); } } @@ -294,7 +294,6 @@ public class AlphabeticalAppsList { mPredictedAppComponents.clear(); mPredictedAppComponents.addAll(apps); onAppsUpdated(); - mAdapter.notifyDataSetChanged(); } /** @@ -311,7 +310,6 @@ public class AlphabeticalAppsList { mApps.clear(); mApps.addAll(apps); onAppsUpdated(); - mAdapter.notifyDataSetChanged(); } /** @@ -320,10 +318,9 @@ public class AlphabeticalAppsList { public void addApps(List<AppInfo> apps) { // We add it in place, in alphabetical order for (AppInfo info : apps) { - addApp(info); + mApps.add(info); } onAppsUpdated(); - mAdapter.notifyDataSetChanged(); } /** @@ -335,11 +332,10 @@ public class AlphabeticalAppsList { if (index != -1) { mApps.set(index, info); } else { - addApp(info); + mApps.add(info); } } onAppsUpdated(); - mAdapter.notifyDataSetChanged(); } /** @@ -353,7 +349,6 @@ public class AlphabeticalAppsList { } } onAppsUpdated(); - mAdapter.notifyDataSetChanged(); } /** @@ -373,58 +368,12 @@ public class AlphabeticalAppsList { } /** - * Implementation to actually add an app to the alphabetic list, but does not notify. - */ - private void addApp(AppInfo info) { - int index = Collections.binarySearch(mApps, info, mAppNameComparator.getAppInfoComparator()); - if (index < 0) { - mApps.add(-(index + 1), info); - } - } - - /** * Updates internals when the set of apps are updated. */ private void onAppsUpdated() { // Sort the list of apps Collections.sort(mApps, mAppNameComparator.getAppInfoComparator()); - // Prepare to update the list of sections, filtered apps, etc. - mFilteredApps.clear(); - mSections.clear(); - mSectionedFilteredApps.clear(); - mFastScrollerSections.clear(); - SectionInfo lastSectionInfo = null; - String lastSectionName = null; - FastScrollSectionInfo lastFastScrollerSectionInfo = null; - int position = 0; - int appIndex = 0; - List<AppInfo> allApps = new ArrayList<>(); - - - // Process the predicted app components - mPredictedApps.clear(); - if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) { - for (ComponentName cn : mPredictedAppComponents) { - for (AppInfo info : mApps) { - if (cn.equals(info.componentName)) { - mPredictedApps.add(info); - break; - } - } - // Stop at the number of predicted apps - if (mPredictedApps.size() == mNumPredictedAppsPerRow) { - break; - } - } - - if (!mPredictedApps.isEmpty()) { - // Create a new spacer for the prediction bar - AdapterItem sectionItem = AdapterItem.asPredictionBarSpacer(position++); - mSectionedFilteredApps.add(sectionItem); - } - } - // As a special case for some languages (currently only Simplified Chinese), we may need to // coalesce sections Locale curLocale = mContext.getResources().getConfiguration().locale; @@ -436,11 +385,7 @@ public class AlphabeticalAppsList { sectionMap = new TreeMap<>(mAppNameComparator.getSectionNameComparator()); for (AppInfo info : mApps) { // Add the section to the cache - String sectionName = mCachedSectionNames.get(info.title); - if (sectionName == null) { - sectionName = mIndexer.computeSectionName(info.title); - mCachedSectionNames.put(info.title, sectionName); - } + String sectionName = getAndUpdateCachedSectionName(info.title); // Add it to the mapping ArrayList<AppInfo> sectionApps = sectionMap.get(sectionName); @@ -451,31 +396,70 @@ public class AlphabeticalAppsList { sectionApps.add(info); } - // Add it to the list + // Add each of the section apps to the list in order + List<AppInfo> allApps = new ArrayList<>(mApps.size()); for (Map.Entry<String, ArrayList<AppInfo>> entry : sectionMap.entrySet()) { allApps.addAll(entry.getValue()); } + mApps = allApps; } else { // Just compute the section headers for use below for (AppInfo info : mApps) { // Add the section to the cache - String sectionName = mCachedSectionNames.get(info.title); - if (sectionName == null) { - sectionName = mIndexer.computeSectionName(info.title); - mCachedSectionNames.put(info.title, sectionName); + getAndUpdateCachedSectionName(info.title); + } + } + + // Recompose the set of adapter items from the current set of apps + updateAdapterItems(); + } + + /** + * Updates the set of filtered apps with the current filter. At this point, we expect + * mCachedSectionNames to have been calculated for the set of all apps in mApps. + */ + private void updateAdapterItems() { + SectionInfo lastSectionInfo = null; + String lastSectionName = null; + FastScrollSectionInfo lastFastScrollerSectionInfo = null; + int position = 0; + int appIndex = 0; + + // Prepare to update the list of sections, filtered apps, etc. + mFilteredApps.clear(); + mFastScrollerSections.clear(); + mAdapterItems.clear(); + mSections.clear(); + + // Process the predicted app components + mPredictedApps.clear(); + if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) { + for (ComponentName cn : mPredictedAppComponents) { + for (AppInfo info : mApps) { + if (cn.equals(info.componentName)) { + mPredictedApps.add(info); + break; + } } + // Stop at the number of predicted apps + if (mPredictedApps.size() == mNumPredictedAppsPerRow) { + break; + } + } + + if (!mPredictedApps.isEmpty()) { + // Create a new spacer for the prediction bar + AdapterItem sectionItem = AdapterItem.asPredictionBarSpacer(position++); + mAdapterItems.add(sectionItem); } - // Add it to the list - allApps.addAll(mApps); } // Recreate the filtered and sectioned apps (for convenience for the grid layout) from the // ordered set of sections - int numApps = allApps.size(); + int numApps = mApps.size(); for (int i = 0; i < numApps; i++) { - AppInfo info = allApps.get(i); - // The section name was computed above so this should be find - String sectionName = mCachedSectionNames.get(info.title); + AppInfo info = mApps.get(i); + String sectionName = getAndUpdateCachedSectionName(info.title); // Check if we want to retain this app if (mFilter != null && !mFilter.retainApp(info, sectionName)) { @@ -494,7 +478,7 @@ public class AlphabeticalAppsList { // Create a new section item to break the flow of items in the list if (!hasFilter()) { AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo); - mSectionedFilteredApps.add(sectionItem); + mAdapterItems.add(sectionItem); } } @@ -505,12 +489,21 @@ public class AlphabeticalAppsList { lastSectionInfo.firstAppItem = appItem; lastFastScrollerSectionInfo.appItem = appItem; } - mSectionedFilteredApps.add(appItem); + mAdapterItems.add(appItem); mFilteredApps.add(info); } // Merge multiple sections together as requested by the merge strategy for this device mergeSections(); + + // Refresh the recycler view + if (mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + + if (mAdapterChangedCallback != null) { + mAdapterChangedCallback.onAdapterItemsChanged(); + } } /** @@ -531,20 +524,20 @@ public class AlphabeticalAppsList { SectionInfo nextSection = mSections.remove(i + 1); // Remove the next section break - mSectionedFilteredApps.remove(nextSection.sectionBreakItem); - int pos = mSectionedFilteredApps.indexOf(section.firstAppItem); + mAdapterItems.remove(nextSection.sectionBreakItem); + int pos = mAdapterItems.indexOf(section.firstAppItem); // Point the section for these new apps to the merged section int nextPos = pos + section.numApps; for (int j = nextPos; j < (nextPos + nextSection.numApps); j++) { - AdapterItem item = mSectionedFilteredApps.get(j); + AdapterItem item = mAdapterItems.get(j); item.sectionInfo = section; item.sectionAppIndex += section.numApps; } // Update the following adapter items of the removed section item - pos = mSectionedFilteredApps.indexOf(nextSection.firstAppItem); - for (int j = pos; j < mSectionedFilteredApps.size(); j++) { - AdapterItem item = mSectionedFilteredApps.get(j); + pos = mAdapterItems.indexOf(nextSection.firstAppItem); + for (int j = pos; j < mAdapterItems.size(); j++) { + AdapterItem item = mAdapterItems.get(j); item.position--; } section.numApps += nextSection.numApps; @@ -560,4 +553,17 @@ public class AlphabeticalAppsList { } } } + + /** + * Returns the cached section name for the given title, recomputing and updating the cache if + * the title has no cached section name. + */ + private String getAndUpdateCachedSectionName(CharSequence title) { + String sectionName = mCachedSectionNames.get(title); + if (sectionName == null) { + sectionName = mIndexer.computeSectionName(title); + mCachedSectionNames.put(title, sectionName); + } + return sectionName; + } } diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java index 76f3c8861..612c19c0f 100644 --- a/src/com/android/launcher3/AppsContainerView.java +++ b/src/com/android/launcher3/AppsContainerView.java @@ -136,7 +136,7 @@ final class HeaderElevationControllerVL implements HeaderElevationController { */ public class AppsContainerView extends BaseContainerView implements DragSource, Insettable, TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable, - AlphabeticalAppsList.FilterChangedCallback, AppsGridAdapter.PredictionBarSpacerCallbacks, + AlphabeticalAppsList.AdapterChangedCallback, AppsGridAdapter.PredictionBarSpacerCallbacks, View.OnTouchListener, View.OnClickListener, View.OnLongClickListener, ViewTreeObserver.OnPreDrawListener { @@ -686,7 +686,7 @@ public class AppsContainerView extends BaseContainerView implements DragSource, } @Override - public void onFilterChanged() { + public void onAdapterItemsChanged() { updatePredictionBarVisibility(); } |