From 0499834db3f9dc6fb0f5f57b5876b8503bce5189 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 5 Jan 2011 13:54:43 -0800 Subject: Fixing issues with holographic outline cache in AllApps/Customize. - Fixing issue where the outline cache was not properly used when changing orientations - Making the outline cache static, and shared across both the AllApps/Customize (since they share an Apps view) - Making sure that holographic outlines for items on only one page are not created, since the holographic outlines will never be shown in that case. - No longer clearing outline cache as frequently Change-Id: I291db3802260249d0470d2637d871958baa8ebff --- src/com/android/launcher2/AllAppsPagedView.java | 7 +- src/com/android/launcher2/CustomizePagedView.java | 54 +++++---- src/com/android/launcher2/PagedView.java | 38 ++----- src/com/android/launcher2/PagedViewIcon.java | 29 ++--- src/com/android/launcher2/PagedViewIconCache.java | 133 ++++++++++++++++++++++ src/com/android/launcher2/PagedViewWidget.java | 28 ++++- 6 files changed, 214 insertions(+), 75 deletions(-) create mode 100644 src/com/android/launcher2/PagedViewIconCache.java diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java index a424bc61c..f7d9f0e49 100644 --- a/src/com/android/launcher2/AllAppsPagedView.java +++ b/src/com/android/launcher2/AllAppsPagedView.java @@ -322,7 +322,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All mApps = list; Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR); mFilteredApps = rebuildFilteredApps(mApps); - mPageViewIconCache.clear(); + mPageViewIconCache.retainAllApps(list); invalidatePageData(); } @@ -367,7 +367,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All int removeIndex = findAppByComponent(mApps, info); if (removeIndex > -1) { mApps.remove(removeIndex); - mPageViewIconCache.removeOutline(info); + mPageViewIconCache.removeOutline(new PagedViewIconCache.Key(info)); } } mFilteredApps = rebuildFilteredApps(mApps); @@ -478,11 +478,12 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All } // Actually reapply to the existing text views + final int numPages = getPageCount(); for (int i = startIndex; i < endIndex; ++i) { final int index = i - startIndex; final ApplicationInfo info = mFilteredApps.get(i); PagedViewIcon icon = (PagedViewIcon) layout.getChildAt(index); - icon.applyFromApplicationInfo(info, mPageViewIconCache, true); + icon.applyFromApplicationInfo(info, mPageViewIconCache, true, (numPages > 1)); PagedViewCellLayout.LayoutParams params = (PagedViewCellLayout.LayoutParams) icon.getLayoutParams(); diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java index d2edd3860..0b874bc11 100644 --- a/src/com/android/launcher2/CustomizePagedView.java +++ b/src/com/android/launcher2/CustomizePagedView.java @@ -180,7 +180,8 @@ public class CustomizePagedView extends PagedViewWithDraggableItems Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR); // Update the widgets/shortcuts to reflect changes in the set of available apps - invalidatePageDataAndIconCache(); + mPageViewIconCache.retainAllApps(list); + invalidatePageData(); } /** @@ -206,7 +207,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems addAppsWithoutInvalidate(list); // Update the widgets/shortcuts to reflect changes in the set of available apps - invalidatePageDataAndIconCache(); + invalidatePageData(); } /** @@ -221,7 +222,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems int removeIndex = findAppByComponent(mApps, info); if (removeIndex > -1) { mApps.remove(removeIndex); - mPageViewIconCache.removeOutline(info); + mPageViewIconCache.removeOutline(new PagedViewIconCache.Key(info)); } } } @@ -233,7 +234,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems removeAppsWithoutInvalidate(list); // Update the widgets/shortcuts to reflect changes in the set of available apps - invalidatePageDataAndIconCache(); + invalidatePageData(); } /** @@ -248,7 +249,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems addAppsWithoutInvalidate(list); // Update the widgets/shortcuts to reflect changes in the set of available apps - invalidatePageDataAndIconCache(); + invalidatePageData(); } /** @@ -295,14 +296,10 @@ public class CustomizePagedView extends PagedViewWithDraggableItems PackageManager.GET_META_DATA); Collections.sort(mWallpaperList, resolveInfoComparator); - invalidatePageDataAndIconCache(); - } - - private void invalidatePageDataAndIconCache() { - // Reset the icon cache - mPageViewIconCache.clear(); - - // Refresh all the tabs + ArrayList retainShortcutList = new ArrayList(mShortcutList); + retainShortcutList.addAll(mWallpaperList); + mPageViewIconCache.retainAllShortcuts(retainShortcutList); + mPageViewIconCache.retainAllAppWidgets(mWidgetList); invalidatePageData(); } @@ -838,6 +835,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems LinearLayout layout = (LinearLayout) getChildAt(page); final ArrayList list = mWidgetPages.get(page); final int count = list.size(); + final int numPages = getPageCount(); layout.removeAllViews(); for (int i = 0; i < count; ++i) { final AppWidgetProviderInfo info = (AppWidgetProviderInfo) list.get(i); @@ -848,7 +846,8 @@ public class CustomizePagedView extends PagedViewWithDraggableItems PagedViewWidget l = (PagedViewWidget) mInflater.inflate( R.layout.customize_paged_view_widget, layout, false); - l.applyFromAppWidgetProviderInfo(info, icon, mMaxWidgetWidth, cellSpans); + l.applyFromAppWidgetProviderInfo(info, icon, mMaxWidgetWidth, cellSpans, + mPageViewIconCache, (numPages > 1)); l.setTag(createItemInfo); l.setOnClickListener(this); l.setOnTouchListener(this); @@ -882,6 +881,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems LinearLayout layout = (LinearLayout) getChildAt(page); layout.removeAllViews(); final int count = mWallpaperList.size(); + final int numPages = getPageCount(); final int numItemsPerPage = mMaxWallpaperCellHSpan / mWallpaperCellHSpan; final int startIndex = page * numItemsPerPage; final int endIndex = Math.min(count, startIndex + numItemsPerPage); @@ -891,7 +891,8 @@ public class CustomizePagedView extends PagedViewWithDraggableItems PagedViewWidget l = (PagedViewWidget) mInflater.inflate( R.layout.customize_paged_view_wallpaper, layout, false); - l.applyFromWallpaperInfo(info, mPackageManager, icon, mMaxWidgetWidth); + l.applyFromWallpaperInfo(info, mPackageManager, icon, mMaxWidgetWidth, + mPageViewIconCache, (numPages > 1)); l.setTag(info); l.setOnClickListener(this); @@ -914,10 +915,11 @@ public class CustomizePagedView extends PagedViewWithDraggableItems private void syncListPageItems(int page, List list) { // ensure that we have the right number of items on the pages - int numCells = mCellCountX * mCellCountY; - int startIndex = page * numCells; - int endIndex = Math.min(startIndex + numCells, list.size()); - PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page); + final int numPages = getPageCount(); + final int numCells = mCellCountX * mCellCountY; + final int startIndex = page * numCells; + final int endIndex = Math.min(startIndex + numCells, list.size()); + final PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page); // TODO: we can optimize by just re-applying to existing views layout.removeAllViews(); for (int i = startIndex; i < endIndex; ++i) { @@ -927,7 +929,8 @@ public class CustomizePagedView extends PagedViewWithDraggableItems PagedViewIcon icon = (PagedViewIcon) mInflater.inflate( R.layout.customize_paged_view_item, layout, false); icon.applyFromResolveInfo(info, mPackageManager, mPageViewIconCache, - ((LauncherApplication) mLauncher.getApplication()).getIconCache()); + ((LauncherApplication) mLauncher.getApplication()).getIconCache(), + (numPages > 1)); switch (mCustomizationType) { case WallpaperCustomization: icon.setOnClickListener(this); @@ -972,17 +975,18 @@ public class CustomizePagedView extends PagedViewWithDraggableItems if (mApps == null) return; // ensure that we have the right number of items on the pages - int numCells = mCellCountX * mCellCountY; - int startIndex = page * numCells; - int endIndex = Math.min(startIndex + numCells, mApps.size()); - PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page); + final int numPages = getPageCount(); + final int numCells = mCellCountX * mCellCountY; + final int startIndex = page * numCells; + final int endIndex = Math.min(startIndex + numCells, mApps.size()); + final PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page); // TODO: we can optimize by just re-applying to existing views layout.removeAllViews(); for (int i = startIndex; i < endIndex; ++i) { final ApplicationInfo info = mApps.get(i); PagedViewIcon icon = (PagedViewIcon) mInflater.inflate( R.layout.all_apps_paged_view_application, layout, false); - icon.applyFromApplicationInfo(info, mPageViewIconCache, true); + icon.applyFromApplicationInfo(info, mPageViewIconCache, true, (numPages > 1)); icon.setOnClickListener(this); icon.setOnTouchListener(this); icon.setOnLongClickListener(this); diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 68833f9af..6c9aac1db 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -16,7 +16,10 @@ package com.android.launcher2; -import com.android.launcher.R; +import java.util.ArrayList; +import java.util.Collection; +import java.util.TreeMap; +import java.util.TreeSet; import android.content.Context; import android.content.res.TypedArray; @@ -34,14 +37,13 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; -import android.view.animation.Animation.AnimationListener; import android.widget.Checkable; import android.widget.Scroller; -import java.util.ArrayList; -import java.util.HashMap; +import com.android.launcher.R; /** * An abstraction of the original Workspace which supports browsing through a @@ -132,7 +134,10 @@ public abstract class PagedView extends ViewGroup { protected int mChoiceMode; private ActionMode mActionMode; - protected PagedViewIconCache mPageViewIconCache; + // NOTE: This is a shared icon cache across all the PagedViews. Currently it is only used in + // AllApps and Customize, and allows them to share holographic icons for the application view + // (which is in both). + protected static PagedViewIconCache mPageViewIconCache = new PagedViewIconCache(); // If true, syncPages and syncPageItems will be called to refresh pages protected boolean mContentIsRefreshable = true; @@ -150,28 +155,6 @@ public abstract class PagedView extends ViewGroup { protected boolean mIsPageMoving = false; - /** - * Simple cache mechanism for PagedViewIcon outlines. - */ - class PagedViewIconCache { - private final HashMap iconOutlineCache = new HashMap(); - - public void clear() { - iconOutlineCache.clear(); - } - public void addOutline(Object key, Bitmap b) { - iconOutlineCache.put(key, b); - } - public void removeOutline(Object key) { - if (iconOutlineCache.containsKey(key)) { - iconOutlineCache.remove(key); - } - } - public Bitmap getOutline(Object key) { - return iconOutlineCache.get(key); - } - } - public interface PageSwitchListener { void onPageSwitch(View newPage, int newPageIndex); } @@ -215,7 +198,6 @@ public abstract class PagedView extends ViewGroup { protected void init() { mDirtyPageContent = new ArrayList(); mDirtyPageContent.ensureCapacity(32); - mPageViewIconCache = new PagedViewIconCache(); mScroller = new Scroller(getContext(), new ScrollInterpolator()); mCurrentPage = 0; mCenterPagesVertically = true; diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java index e4049eb19..6ce308b1d 100644 --- a/src/com/android/launcher2/PagedViewIcon.java +++ b/src/com/android/launcher2/PagedViewIcon.java @@ -32,7 +32,6 @@ import android.util.AttributeSet; import android.widget.Checkable; import com.android.launcher.R; -import com.android.launcher2.PagedView.PagedViewIconCache; @@ -50,7 +49,7 @@ public class PagedViewIcon extends CacheableTextView implements Checkable { private Bitmap mHolographicOutline; private Bitmap mIcon; - private Object mIconCacheKey; + private PagedViewIconCache.Key mIconCacheKey; private PagedViewIconCache mIconCache; private int mAlpha = 255; @@ -140,26 +139,23 @@ public class PagedViewIcon extends CacheableTextView implements Checkable { } public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache, - boolean scaleUp) { - mIconCache = cache; - mIconCacheKey = info; - mHolographicOutline = mIconCache.getOutline(mIconCacheKey); - + boolean scaleUp, boolean createHolographicOutlines) { mIcon = info.iconBitmap; setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null); setText(info.title); buildAndEnableCache(); setTag(info); - queueHolographicOutlineCreation(); + if (createHolographicOutlines) { + mIconCache = cache; + mIconCacheKey = new PagedViewIconCache.Key(info); + mHolographicOutline = mIconCache.getOutline(mIconCacheKey); + queueHolographicOutlineCreation(); + } } public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager, - PagedViewIconCache cache, IconCache modelIconCache) { - mIconCache = cache; - mIconCacheKey = info; - mHolographicOutline = mIconCache.getOutline(mIconCacheKey); - + PagedViewIconCache cache, IconCache modelIconCache, boolean createHolographicOutlines) { mIcon = Utilities.createIconBitmap( modelIconCache.getFullResIcon(info, packageManager), mContext); setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null); @@ -167,7 +163,12 @@ public class PagedViewIcon extends CacheableTextView implements Checkable { buildAndEnableCache(); setTag(info); - queueHolographicOutlineCreation(); + if (createHolographicOutlines) { + mIconCache = cache; + mIconCacheKey = new PagedViewIconCache.Key(info); + mHolographicOutline = mIconCache.getOutline(mIconCacheKey); + queueHolographicOutlineCreation(); + } } @Override diff --git a/src/com/android/launcher2/PagedViewIconCache.java b/src/com/android/launcher2/PagedViewIconCache.java new file mode 100644 index 000000000..de05ff1ac --- /dev/null +++ b/src/com/android/launcher2/PagedViewIconCache.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher2; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import android.appwidget.AppWidgetProviderInfo; +import android.content.ComponentName; +import android.content.pm.ComponentInfo; +import android.content.pm.ResolveInfo; +import android.graphics.Bitmap; + +/** + * Simple cache mechanism for PagedView outlines. + */ +public class PagedViewIconCache { + public static class Key { + public enum Type { + ApplicationInfoKey, + AppWidgetProviderInfoKey, + ResolveInfoKey + } + private final ComponentName mComponentName; + private final Type mType; + + public Key(ApplicationInfo info) { + mComponentName = info.componentName; + mType = Type.ApplicationInfoKey; + } + public Key(ResolveInfo info) { + final ComponentInfo ci = info.activityInfo != null ? info.activityInfo : + info.serviceInfo; + mComponentName = new ComponentName(ci.packageName, ci.name); + mType = Type.AppWidgetProviderInfoKey; + } + public Key(AppWidgetProviderInfo info) { + mComponentName = info.provider; + mType = Type.ResolveInfoKey; + } + + private ComponentName getComponentName() { + return mComponentName; + } + public boolean isKeyType(Type t) { + return (mType == t); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Key) { + Key k = (Key) o; + return mComponentName.equals(k.mComponentName); + } + return super.equals(o); + } + @Override + public int hashCode() { + return getComponentName().hashCode(); + } + } + + private final HashMap mIconOutlineCache = new HashMap(); + + public void clear() { + for (Key key : mIconOutlineCache.keySet()) { + mIconOutlineCache.get(key).recycle(); + } + mIconOutlineCache.clear(); + } + private void retainAll(HashSet keysToKeep, Key.Type t) { + HashSet keysToRemove = new HashSet(mIconOutlineCache.keySet()); + keysToRemove.removeAll(keysToKeep); + for (Key key : keysToRemove) { + if (key.isKeyType(t)) { + mIconOutlineCache.get(key).recycle(); + mIconOutlineCache.remove(key); + } + } + } + /** Removes all the keys to applications that aren't in the passed in collection */ + public void retainAllApps(ArrayList keys) { + HashSet keysSet = new HashSet(); + for (ApplicationInfo info : keys) { + keysSet.add(new Key(info)); + } + retainAll(keysSet, Key.Type.ApplicationInfoKey); + } + /** Removes all the keys to shortcuts that aren't in the passed in collection */ + public void retainAllShortcuts(List keys) { + HashSet keysSet = new HashSet(); + for (ResolveInfo info : keys) { + keysSet.add(new Key(info)); + } + retainAll(keysSet, Key.Type.ResolveInfoKey); + } + /** Removes all the keys to widgets that aren't in the passed in collection */ + public void retainAllAppWidgets(List keys) { + HashSet keysSet = new HashSet(); + for (AppWidgetProviderInfo info : keys) { + keysSet.add(new Key(info)); + } + retainAll(keysSet, Key.Type.AppWidgetProviderInfoKey); + } + public void addOutline(Key key, Bitmap b) { + mIconOutlineCache.put(key, b); + } + public void removeOutline(Key key) { + if (mIconOutlineCache.containsKey(key)) { + mIconOutlineCache.get(key).recycle(); + mIconOutlineCache.remove(key); + } + } + public Bitmap getOutline(Key key) { + return mIconOutlineCache.get(key); + } +} diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java index 8c729b1ca..07a59eec4 100644 --- a/src/com/android/launcher2/PagedViewWidget.java +++ b/src/com/android/launcher2/PagedViewWidget.java @@ -52,6 +52,9 @@ public class PagedViewWidget extends LinearLayout implements Checkable { private final Canvas mHolographicOutlineCanvas = new Canvas(); private FastBitmapDrawable mPreview; + private PagedViewIconCache.Key mIconCacheKey; + private PagedViewIconCache mIconCache; + private int mAlpha = 255; private int mHolographicAlpha; @@ -97,6 +100,7 @@ public class PagedViewWidget extends LinearLayout implements Checkable { mHandler.post(new Runnable() { public void run() { widget.mHolographicOutline = outline; + widget.mIconCache.addOutline(widget.mIconCacheKey, outline); widget.invalidate(); } }); @@ -140,7 +144,7 @@ public class PagedViewWidget extends LinearLayout implements Checkable { private void queueHolographicOutlineCreation() { // Generate the outline in the background - if (mHolographicOutline == null) { + if (mHolographicOutline == null && mPreview != null) { Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE); m.obj = this; sWorker.sendMessage(m); @@ -148,7 +152,8 @@ public class PagedViewWidget extends LinearLayout implements Checkable { } public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info, - FastBitmapDrawable preview, int maxWidth, int[] cellSpan) { + FastBitmapDrawable preview, int maxWidth, int[] cellSpan, + PagedViewIconCache cache, boolean createHolographicOutline) { final ImageView image = (ImageView) findViewById(R.id.widget_preview); image.setMaxWidth(maxWidth); image.setImageDrawable(preview); @@ -156,17 +161,30 @@ public class PagedViewWidget extends LinearLayout implements Checkable { name.setText(info.label); final TextView dims = (TextView) findViewById(R.id.widget_dims); dims.setText(mContext.getString(R.string.widget_dims_format, cellSpan[0], cellSpan[1])); - mPreview = preview; + + if (createHolographicOutline) { + mIconCache = cache; + mIconCacheKey = new PagedViewIconCache.Key(info); + mHolographicOutline = mIconCache.getOutline(mIconCacheKey); + mPreview = preview; + } } public void applyFromWallpaperInfo(ResolveInfo info, PackageManager packageManager, - FastBitmapDrawable preview, int maxWidth) { + FastBitmapDrawable preview, int maxWidth, PagedViewIconCache cache, + boolean createHolographicOutline) { ImageView image = (ImageView) findViewById(R.id.wallpaper_preview); image.setMaxWidth(maxWidth); image.setImageDrawable(preview); TextView name = (TextView) findViewById(R.id.wallpaper_name); name.setText(info.loadLabel(packageManager)); - mPreview = preview; + + if (createHolographicOutline) { + mIconCache = cache; + mIconCacheKey = new PagedViewIconCache.Key(info); + mHolographicOutline = mIconCache.getOutline(mIconCacheKey); + mPreview = preview; + } } @Override -- cgit v1.2.3