mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 23:36:47 +00:00
Fixing minor memory leak with name comparator.
- WidgetsAndShortcutNameComparator was using the actual widget and shortcut resolve infos as the key to the label cache. Neither of these classes override hashCode() and we were retrieving a new set of widgets and shortcuts whenever packages changed so we would end up creating more and more entries in the cache. This isn't a huge leak, but could lead to problems if Launcher is used for long periods without being killed. - Now, we use a ComponentKey as the key, so that we don't keep a reference to the widget/shortcut infos and also ensures that they should hash to the same labels. Change-Id: I91347ee72363adbc2b075b67dba331e35ab1fe34
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.AppWidgetManagerCompat;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.Comparator;
|
||||
@@ -16,53 +17,81 @@ import java.util.HashMap;
|
||||
public class WidgetsAndShortcutNameComparator implements Comparator<Object> {
|
||||
private final AppWidgetManagerCompat mManager;
|
||||
private final PackageManager mPackageManager;
|
||||
private final HashMap<Object, String> mLabelCache;
|
||||
private final HashMap<ComponentKey, String> mLabelCache;
|
||||
private final Collator mCollator;
|
||||
private final UserHandleCompat mMainHandle;
|
||||
|
||||
public WidgetsAndShortcutNameComparator(Context context) {
|
||||
mManager = AppWidgetManagerCompat.getInstance(context);
|
||||
mPackageManager = context.getPackageManager();
|
||||
mLabelCache = new HashMap<Object, String>();
|
||||
mLabelCache = new HashMap<>();
|
||||
mCollator = Collator.getInstance();
|
||||
mMainHandle = UserHandleCompat.myUserHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets any stored state.
|
||||
*/
|
||||
public void reset() {
|
||||
mLabelCache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int compare(Object a, Object b) {
|
||||
String labelA, labelB;
|
||||
if (mLabelCache.containsKey(a)) {
|
||||
labelA = mLabelCache.get(a);
|
||||
} else {
|
||||
labelA = (a instanceof LauncherAppWidgetProviderInfo)
|
||||
? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) a))
|
||||
: Utilities.trim(((ResolveInfo) a).loadLabel(mPackageManager));
|
||||
mLabelCache.put(a, labelA);
|
||||
}
|
||||
if (mLabelCache.containsKey(b)) {
|
||||
labelB = mLabelCache.get(b);
|
||||
} else {
|
||||
labelB = (b instanceof LauncherAppWidgetProviderInfo)
|
||||
? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) b))
|
||||
: Utilities.trim(((ResolveInfo) b).loadLabel(mPackageManager));
|
||||
mLabelCache.put(b, labelB);
|
||||
}
|
||||
|
||||
// Currently, there is no work profile shortcuts, hence only considering the widget cases.
|
||||
|
||||
boolean aWorkProfile = (a instanceof LauncherAppWidgetProviderInfo) &&
|
||||
!mMainHandle.equals(mManager.getUser((LauncherAppWidgetProviderInfo) a));
|
||||
boolean bWorkProfile = (b instanceof LauncherAppWidgetProviderInfo) &&
|
||||
!mMainHandle.equals(mManager.getUser((LauncherAppWidgetProviderInfo) b));
|
||||
public final int compare(Object objA, Object objB) {
|
||||
ComponentKey keyA = getComponentKey(objA);
|
||||
ComponentKey keyB = getComponentKey(objB);
|
||||
|
||||
// Independent of how the labels compare, if only one of the two widget info belongs to
|
||||
// work profile, put that one in the back.
|
||||
boolean aWorkProfile = !mMainHandle.equals(keyA.user);
|
||||
boolean bWorkProfile = !mMainHandle.equals(keyB.user);
|
||||
if (aWorkProfile && !bWorkProfile) {
|
||||
return 1;
|
||||
}
|
||||
if (!aWorkProfile && bWorkProfile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get the labels for comparison
|
||||
String labelA = mLabelCache.get(keyA);
|
||||
String labelB = mLabelCache.get(keyB);
|
||||
if (labelA == null) {
|
||||
labelA = getLabel(objA);
|
||||
mLabelCache.put(keyA, labelA);
|
||||
}
|
||||
if (labelB == null) {
|
||||
labelB = getLabel(objB);
|
||||
mLabelCache.put(keyB, labelB);
|
||||
}
|
||||
return mCollator.compare(labelA, labelB);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a component key for the given widget or shortcut info.
|
||||
*/
|
||||
private ComponentKey getComponentKey(Object o) {
|
||||
if (o instanceof LauncherAppWidgetProviderInfo) {
|
||||
LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o;
|
||||
return new ComponentKey(widgetInfo.provider, mManager.getUser(widgetInfo));
|
||||
} else {
|
||||
ResolveInfo shortcutInfo = (ResolveInfo) o;
|
||||
ComponentName cn = new ComponentName(shortcutInfo.activityInfo.packageName,
|
||||
shortcutInfo.activityInfo.name);
|
||||
// Currently, there are no work profile shortcuts
|
||||
return new ComponentKey(cn, UserHandleCompat.myUserHandle());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the label for the given widget or shortcut info. This may be an expensive call.
|
||||
*/
|
||||
private String getLabel(Object o) {
|
||||
if (o instanceof LauncherAppWidgetProviderInfo) {
|
||||
LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o;
|
||||
return Utilities.trim(mManager.loadLabel(widgetInfo));
|
||||
} else {
|
||||
ResolveInfo shortcutInfo = (ResolveInfo) o;
|
||||
return Utilities.trim(shortcutInfo.loadLabel(mPackageManager));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ public class WidgetsModel {
|
||||
private ArrayList<Object> mRawList;
|
||||
|
||||
private final AppWidgetManagerCompat mAppWidgetMgr;
|
||||
private final Comparator mWidgetAndShortcutNameComparator;
|
||||
private final WidgetsAndShortcutNameComparator mWidgetAndShortcutNameComparator;
|
||||
private final Comparator mAppNameComparator;
|
||||
private final IconCache mIconCache;
|
||||
private final AppFilter mAppFilter;
|
||||
@@ -103,6 +103,7 @@ public class WidgetsModel {
|
||||
// clear the lists.
|
||||
mWidgetsList.clear();
|
||||
mPackageItemInfos.clear();
|
||||
mWidgetAndShortcutNameComparator.reset();
|
||||
|
||||
// add and update.
|
||||
for (Object o: rawWidgetsShortcuts) {
|
||||
@@ -139,7 +140,7 @@ public class WidgetsModel {
|
||||
if (widgetsShortcutsList != null) {
|
||||
widgetsShortcutsList.add(o);
|
||||
} else {
|
||||
widgetsShortcutsList = new ArrayList<Object>();
|
||||
widgetsShortcutsList = new ArrayList<>();
|
||||
widgetsShortcutsList.add(o);
|
||||
pInfo = new PackageItemInfo(packageName);
|
||||
mIconCache.getTitleAndIconForApp(packageName, userHandle,
|
||||
|
||||
Reference in New Issue
Block a user