Moving section names to model, to avoid an unnecessary hashmap

Change-Id: I9620367e0c2203b2290a4a188411ccb9174ae130
This commit is contained in:
Sunny Goyal
2019-08-06 15:21:36 -07:00
parent 91e7a72217
commit 0af5134bc5
4 changed files with 35 additions and 109 deletions
+3
View File
@@ -49,6 +49,9 @@ public class AppInfo extends ItemInfoWithIcon {
public ComponentName componentName;
// Section name used for indexing.
public String sectionName = "";
public AppInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
@@ -21,16 +21,13 @@ import android.content.pm.PackageManager;
import com.android.launcher3.AppInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LabelComparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -145,9 +142,7 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
// The of ordered component names as a result of a search query
private ArrayList<ComponentKey> mSearchResults;
private HashMap<CharSequence, String> mCachedSectionNames = new HashMap<>();
private AllAppsGridAdapter mAdapter;
private AlphabeticIndexCompat mIndexer;
private AppInfoComparator mAppNameComparator;
private final int mNumAppsPerRow;
private int mNumAppRowsInAdapter;
@@ -156,7 +151,6 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
public AlphabeticalAppsList(Context context, AllAppsStore appsStore, boolean isWork) {
mAllAppsStore = appsStore;
mLauncher = Launcher.getLauncher(context);
mIndexer = new AlphabeticIndexCompat(context);
mAppNameComparator = new AppInfoComparator(context);
mIsWork = isWork;
mNumAppsPerRow = mLauncher.getDeviceProfile().inv.numColumns;
@@ -263,7 +257,7 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
TreeMap<String, ArrayList<AppInfo>> sectionMap = new TreeMap<>(new LabelComparator());
for (AppInfo info : mApps) {
// Add the section to the cache
String sectionName = getAndUpdateCachedSectionName(info.title);
String sectionName = info.sectionName;
// Add it to the mapping
ArrayList<AppInfo> sectionApps = sectionMap.get(sectionName);
@@ -279,12 +273,6 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
for (Map.Entry<String, ArrayList<AppInfo>> entry : sectionMap.entrySet()) {
mApps.addAll(entry.getValue());
}
} else {
// Just compute the section headers for use below
for (AppInfo info : mApps) {
// Add the section to the cache
getAndUpdateCachedSectionName(info.title);
}
}
// Recompose the set of adapter items from the current set of apps
@@ -320,7 +308,7 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
// Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
// ordered set of sections
for (AppInfo info : getFiltersAppInfos()) {
String sectionName = getAndUpdateCachedSectionName(info.title);
String sectionName = info.sectionName;
// Create a new section if the section names do not match
if (!sectionName.equals(lastSectionName)) {
@@ -428,18 +416,4 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
}
return result;
}
/**
* 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;
}
}
@@ -3,7 +3,6 @@ package com.android.launcher3.compat;
import android.content.Context;
import android.icu.text.AlphabeticIndex;
import android.os.LocaleList;
import android.util.Log;
import com.android.launcher3.Utilities;
@@ -12,28 +11,32 @@ import java.util.Locale;
import androidx.annotation.NonNull;
public class AlphabeticIndexCompat {
private static final String TAG = "AlphabeticIndexCompat";
private static final String MID_DOT = "\u2219";
private final BaseIndex mBaseIndex;
private final String mDefaultMiscLabel;
private final AlphabeticIndex.ImmutableIndex mBaseIndex;
public AlphabeticIndexCompat(Context context) {
BaseIndex index = null;
this(context.getResources().getConfiguration().getLocales());
}
try {
index = new AlphabeticIndexVN(context);
} catch (Exception e) {
Log.d(TAG, "Unable to load the system index", e);
public AlphabeticIndexCompat(LocaleList locales) {
int localeCount = locales.size();
Locale primaryLocale = localeCount == 0 ? Locale.ENGLISH : locales.get(0);
AlphabeticIndex indexBuilder = new AlphabeticIndex(primaryLocale);
for (int i = 1; i < localeCount; i++) {
indexBuilder.addLabels(locales.get(i));
}
indexBuilder.addLabels(Locale.ENGLISH);
mBaseIndex = indexBuilder.buildImmutableIndex();
mBaseIndex = index == null ? new BaseIndex() : index;
if (context.getResources().getConfiguration().locale
.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
if (primaryLocale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
// Japanese character 他 ("misc")
mDefaultMiscLabel = "\u4ed6";
// TODO(winsonc, omakoto): We need to handle Japanese sections better, especially the kanji
// TODO(winsonc, omakoto): We need to handle Japanese sections better,
// especially the kanji
} else {
// Dot
mDefaultMiscLabel = MID_DOT;
@@ -45,7 +48,7 @@ public class AlphabeticIndexCompat {
*/
public String computeSectionName(@NonNull CharSequence cs) {
String s = Utilities.trim(cs);
String sectionName = mBaseIndex.getBucketLabel(mBaseIndex.getBucketIndex(s));
String sectionName = mBaseIndex.getBucket(mBaseIndex.getBucketIndex(s)).getLabel();
if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) {
int c = s.codePointAt(0);
boolean startsWithDigit = Character.isDigit(c);
@@ -66,71 +69,4 @@ public class AlphabeticIndexCompat {
}
return sectionName;
}
/**
* Base class to support Alphabetic indexing if not supported by the framework.
* TODO(winsonc): disable for non-english locales
*/
private static class BaseIndex {
private static final String BUCKETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-";
private static final int UNKNOWN_BUCKET_INDEX = BUCKETS.length() - 1;
/**
* Returns the index of the bucket in which the given string should appear.
*/
protected int getBucketIndex(@NonNull String s) {
if (s.isEmpty()) {
return UNKNOWN_BUCKET_INDEX;
}
int index = BUCKETS.indexOf(s.substring(0, 1).toUpperCase());
if (index != -1) {
return index;
}
return UNKNOWN_BUCKET_INDEX;
}
/**
* Returns the label for the bucket at the given index (as returned by getBucketIndex).
*/
protected String getBucketLabel(int index) {
return BUCKETS.substring(index, index + 1);
}
}
/**
* Implementation based on {@link AlphabeticIndex}.
*/
private static class AlphabeticIndexVN extends BaseIndex {
private final AlphabeticIndex.ImmutableIndex mAlphabeticIndex;
public AlphabeticIndexVN(Context context) {
LocaleList locales = context.getResources().getConfiguration().getLocales();
int localeCount = locales.size();
Locale primaryLocale = localeCount == 0 ? Locale.ENGLISH : locales.get(0);
AlphabeticIndex indexBuilder = new AlphabeticIndex(primaryLocale);
for (int i = 1; i < localeCount; i++) {
indexBuilder.addLabels(locales.get(i));
}
indexBuilder.addLabels(Locale.ENGLISH);
mAlphabeticIndex = indexBuilder.buildImmutableIndex();
}
/**
* Returns the index of the bucket in which {@param s} should appear.
*/
protected int getBucketIndex(String s) {
return mAlphabeticIndex.getBucketIndex(s);
}
/**
* Returns the label for the bucket at the given index
*/
protected String getBucketLabel(int index) {
return mAlphabeticIndex.getBucket(index).getLabel();
}
}
}
@@ -23,6 +23,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.os.LocaleList;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
@@ -30,6 +31,7 @@ import android.util.Log;
import com.android.launcher3.AppFilter;
import com.android.launcher3.AppInfo;
import com.android.launcher3.PromiseAppInfo;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
@@ -68,12 +70,15 @@ public class AllAppsList {
private boolean mDataChanged = false;
private Consumer<AppInfo> mRemoveListener = NO_OP_CONSUMER;
private AlphabeticIndexCompat mIndex;
/**
* Boring constructor.
*/
public AllAppsList(IconCache iconCache, AppFilter appFilter) {
mIconCache = iconCache;
mAppFilter = appFilter;
mIndex = new AlphabeticIndexCompat(LocaleList.getDefault());
}
/**
@@ -99,6 +104,7 @@ public class AllAppsList {
return;
}
mIconCache.getTitleAndIcon(info, activityInfo, true /* useLowResIcon */);
info.sectionName = mIndex.computeSectionName(info.title);
data.add(info);
mDataChanged = true;
@@ -112,6 +118,8 @@ public class AllAppsList {
if (applicationInfo == null) {
PromiseAppInfo info = new PromiseAppInfo(installInfo);
mIconCache.getTitleAndIcon(info, info.usingLowResIcon());
info.sectionName = mIndex.computeSectionName(info.title);
data.add(info);
mDataChanged = true;
}
@@ -148,6 +156,8 @@ public class AllAppsList {
public void clear() {
data.clear();
mDataChanged = false;
// Reset the index as locales might have changed
mIndex = new AlphabeticIndexCompat(LocaleList.getDefault());
}
/**
@@ -194,6 +204,7 @@ public class AllAppsList {
for (AppInfo info : data) {
if (info.user.equals(user) && packages.contains(info.componentName.getPackageName())) {
mIconCache.updateTitleAndIcon(info);
info.sectionName = mIndex.computeSectionName(info.title);
mDataChanged = true;
}
}
@@ -228,6 +239,8 @@ public class AllAppsList {
add(new AppInfo(context, info, user), info);
} else {
mIconCache.getTitleAndIcon(applicationInfo, info, true /* useLowResIcon */);
applicationInfo.sectionName = mIndex.computeSectionName(applicationInfo.title);
mDataChanged = true;
}
}