aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorherriojr <jherriott@cyngn.com>2015-07-22 09:12:34 -0700
committerJon Herriott <jherriott@cyngn.com>2015-07-27 12:24:51 -0700
commitff95c1c0fbae93f70e81c7b27d43d1d534fe0e09 (patch)
treeee8d3ce522d2557c77971f9fdf0305acbdebeb10
parent82efc98e8b1bc96728c0ee6a5fbc374f230e443c (diff)
downloadandroid_packages_apps_CMFileManager-ff95c1c0fbae93f70e81c7b27d43d1d534fe0e09.tar.gz
android_packages_apps_CMFileManager-ff95c1c0fbae93f70e81c7b27d43d1d534fe0e09.tar.bz2
android_packages_apps_CMFileManager-ff95c1c0fbae93f70e81c7b27d43d1d534fe0e09.zip
Refactored the ImageLoader a bit, so that it doesn't have trouble
loading images. There were a couple of problem causing this, so I felt it best to change the implementation. Change-Id: Ic77a94681d77fa4fba49f3f24f40e260220b925a Ticket: QRDL-905 (cherry picked from commit c310a84552206b25705d2e7d2113c95ce29d8ecf)
-rw-r--r--src/com/cyanogenmod/filemanager/adapters/FileSystemObjectAdapter.java4
-rw-r--r--src/com/cyanogenmod/filemanager/adapters/SearchResultAdapter.java3
-rw-r--r--src/com/cyanogenmod/filemanager/ui/IconHolder.java302
3 files changed, 157 insertions, 152 deletions
diff --git a/src/com/cyanogenmod/filemanager/adapters/FileSystemObjectAdapter.java b/src/com/cyanogenmod/filemanager/adapters/FileSystemObjectAdapter.java
index c43819f4..49ec6c69 100644
--- a/src/com/cyanogenmod/filemanager/adapters/FileSystemObjectAdapter.java
+++ b/src/com/cyanogenmod/filemanager/adapters/FileSystemObjectAdapter.java
@@ -291,10 +291,6 @@ public class FileSystemObjectAdapter
}
//Set the data
- if (convertView != null) {
- // Cancel load for previous usage
- mIconHolder.cancelLoad(viewHolder.mIvIcon);
- }
mIconHolder.loadDrawable(viewHolder.mIvIcon, getItem(position), dataHolder.mDwIcon);
viewHolder.mTvName.setText(dataHolder.mName);
diff --git a/src/com/cyanogenmod/filemanager/adapters/SearchResultAdapter.java b/src/com/cyanogenmod/filemanager/adapters/SearchResultAdapter.java
index 32775c8a..7cde6d61 100644
--- a/src/com/cyanogenmod/filemanager/adapters/SearchResultAdapter.java
+++ b/src/com/cyanogenmod/filemanager/adapters/SearchResultAdapter.java
@@ -443,9 +443,6 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
ViewHolder viewHolder = (ViewHolder) v.getTag();
//Set the data
- if (convertView != null) {
- mIconHolder.cancelLoad(viewHolder.mIvIcon);
- }
mIconHolder.loadDrawable(viewHolder.mIvIcon,
getItem(position).getFso(), dataHolder.mDwIcon);
diff --git a/src/com/cyanogenmod/filemanager/ui/IconHolder.java b/src/com/cyanogenmod/filemanager/ui/IconHolder.java
index 2f658647..29a8b856 100644
--- a/src/com/cyanogenmod/filemanager/ui/IconHolder.java
+++ b/src/com/cyanogenmod/filemanager/ui/IconHolder.java
@@ -39,8 +39,10 @@ import com.cyanogenmod.filemanager.util.FileHelper;
import com.cyanogenmod.filemanager.util.MediaHelper;
import com.cyanogenmod.filemanager.util.MimeTypeHelper.KnownMimeTypeResolver;
+import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.WeakHashMap;
import java.util.Map;
/**
@@ -52,14 +54,13 @@ public class IconHolder {
private static final int MSG_LOAD = 1;
private static final int MSG_LOADED = 2;
- private static final int MSG_DESTROY = 3;
private final Map<String, Drawable> mIcons; // Themes based
private final Map<String, Drawable> mAppIcons; // App based
private Map<String, Long> mAlbums; // Media albums
- private Map<ImageView, FileSystemObject> mRequests;
+ private final WeakHashMap<ImageView, Loadable> mRequests;
private final Context mContext;
private final boolean mUseThumbs;
@@ -68,9 +69,133 @@ public class IconHolder {
private HandlerThread mWorkerThread;
private Handler mWorkerHandler;
- private static class LoadResult {
+ /**
+ * This is kind of a hack, we should have a loadable for each MimeType we run into.
+ * TODO: Refactor this to have different loadables
+ */
+ private static class Loadable {
+ private Context mContext;
+ private static boolean sAlbumsDirty = true;
+ private static Map<String, Long> sAlbums;
+
FileSystemObject fso;
+ WeakReference<ImageView> view;
Drawable result;
+
+ public Loadable(Context context, ImageView view, FileSystemObject fso) {
+ this.mContext = context.getApplicationContext();
+ this.fso = fso;
+ this.view = new WeakReference<ImageView>(view);
+ this.result = null;
+ }
+
+ private static synchronized Map<String, Long> getAlbums(Context context) {
+ if (sAlbumsDirty) {
+ sAlbums = MediaHelper.getAllAlbums(context.getContentResolver());
+ sAlbumsDirty = false;
+ }
+ return sAlbums;
+ }
+
+ public static synchronized void dirtyAlbums() {
+ sAlbumsDirty = true;
+ }
+
+ public boolean load() {
+ return (result = loadDrawable(fso)) != null;
+ }
+
+ private Drawable loadDrawable(FileSystemObject fso) {
+ final String filePath = MediaHelper.normalizeMediaPath(fso.getFullPath());
+
+ if (KnownMimeTypeResolver.isAndroidApp(mContext, fso)) {
+ return getAppDrawable(fso);
+ } else if (KnownMimeTypeResolver.isImage(mContext, fso)) {
+ return getImageDrawable(filePath);
+ } else if (KnownMimeTypeResolver.isVideo(mContext, fso)) {
+ return getVideoDrawable(filePath);
+ } else if (FileHelper.isDirectory(fso)) {
+ Map<String, Long> albums = getAlbums(mContext);
+ if (albums.containsKey(filePath)) {
+ return getAlbumDrawable(albums.get(filePath));
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Method that returns the main icon of the app
+ *
+ * @param fso The FileSystemObject
+ * @return Drawable The drawable or null if cannot be extracted
+ */
+ private Drawable getAppDrawable(FileSystemObject fso) {
+ final String filepath = fso.getFullPath();
+ PackageManager pm = mContext.getPackageManager();
+ PackageInfo packageInfo = pm.getPackageArchiveInfo(filepath,
+ PackageManager.GET_ACTIVITIES);
+ if (packageInfo != null) {
+ // Read http://code.google.com/p/android/issues/detail?id=9151, CM fixed this
+ // issue. We retain it for compatibility with older versions and roms without
+ // this fix. Required to access apk which are not installed.
+ final ApplicationInfo appInfo = packageInfo.applicationInfo;
+ appInfo.sourceDir = filepath;
+ appInfo.publicSourceDir = filepath;
+ return pm.getDrawable(appInfo.packageName, appInfo.icon, appInfo);
+ }
+ return null;
+ }
+
+ /**
+ * Method that returns a thumbnail of the picture
+ *
+ * @param file The path to the file
+ * @return Drawable The drawable or null if cannot be extracted
+ */
+ private Drawable getImageDrawable(String file) {
+ Bitmap thumb = ThumbnailUtils.createImageThumbnail(
+ MediaHelper.normalizeMediaPath(file),
+ ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL);
+ if (thumb == null) {
+ return null;
+ }
+ return new BitmapDrawable(mContext.getResources(), thumb);
+ }
+
+ /**
+ * Method that returns a thumbnail of the video
+ *
+ * @param file The path to the file
+ * @return Drawable The drawable or null if cannot be extracted
+ */
+ private Drawable getVideoDrawable(String file) {
+ Bitmap thumb = ThumbnailUtils.createVideoThumbnail(
+ MediaHelper.normalizeMediaPath(file),
+ ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL);
+ if (thumb == null) {
+ return null;
+ }
+ return new BitmapDrawable(mContext.getResources(), thumb);
+ }
+
+ /**
+ * Method that returns a thumbnail of the album folder
+ *
+ * @param albumId The album identifier
+ * @return Drawable The drawable or null if cannot be extracted
+ */
+ private Drawable getAlbumDrawable(long albumId) {
+ String path = MediaHelper.getAlbumThumbnailPath(mContext.getContentResolver(), albumId);
+ if (path == null) {
+ return null;
+ }
+ Bitmap thumb = ThumbnailUtils.createImageThumbnail(path,
+ ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL);
+ if (thumb == null) {
+ return null;
+ }
+ return new BitmapDrawable(mContext.getResources(), thumb);
+ }
}
private Handler mHandler = new Handler() {
@@ -78,39 +203,35 @@ public class IconHolder {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LOADED:
- processResult((LoadResult) msg.obj);
- sendEmptyMessageDelayed(MSG_DESTROY, 3000);
- break;
- case MSG_DESTROY:
- shutdownWorker();
+ processResult((Loadable) msg.obj);
break;
}
}
- private void processResult(LoadResult result) {
+ private void processResult(Loadable result) {
+ ImageView view = result.view.get();
+ if (view == null) {
+ return;
+ }
+
+ Loadable requestedForImageView = mRequests.get(view);
+ if (requestedForImageView != result) {
+ return;
+ }
+
// Cache the new drawable
final String filePath = MediaHelper.normalizeMediaPath(result.fso.getFullPath());
- mAppIcons.put(filePath, result.result);
-
- // find the request for it
- for (Map.Entry<ImageView, FileSystemObject> entry : mRequests.entrySet()) {
- final ImageView imageView = entry.getKey();
- final FileSystemObject fso = entry.getValue();
- if (fso == result.fso) {
- imageView.setImageDrawable(result.result);
- mRequests.remove(imageView);
- break;
- }
+ if (result.result != null) {
+ mAppIcons.put(filePath, result.result);
}
+ view.setImageDrawable(result.result);
}
};
private ContentObserver mMediaObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
- synchronized (this) {
- mNeedAlbumUpdate = true;
- }
+ Loadable.dirtyAlbums();
}
};
@@ -124,7 +245,7 @@ public class IconHolder {
super();
this.mContext = context;
this.mUseThumbs = useThumbs;
- this.mRequests = new HashMap<ImageView, FileSystemObject>();
+ this.mRequests = new WeakHashMap<ImageView, Loadable>();
this.mIcons = new HashMap<String, Drawable>();
this.mAppIcons = new LinkedHashMap<String, Drawable>(MAX_CACHE, .75F, true) {
private static final long serialVersionUID = 1L;
@@ -182,28 +303,21 @@ public class IconHolder {
return;
}
- mRequests.put(iconView, fso);
- iconView.setImageDrawable(defaultIcon);
-
- mHandler.removeMessages(MSG_DESTROY);
if (mWorkerThread == null) {
mWorkerThread = new HandlerThread("IconHolderLoader");
mWorkerThread.start();
mWorkerHandler = new WorkerHandler(mWorkerThread.getLooper());
}
- Message msg = mWorkerHandler.obtainMessage(MSG_LOAD, fso);
- msg.sendToTarget();
- }
-
- /**
- * Cancel loading of a drawable for a certain ImageView.
- */
- public void cancelLoad(ImageView view) {
- FileSystemObject fso = mRequests.get(view);
- if (fso != null && mWorkerHandler != null) {
- mWorkerHandler.removeMessages(MSG_LOAD, fso);
+ Loadable previousForView = mRequests.get(iconView);
+ if (previousForView != null) {
+ mWorkerHandler.removeMessages(MSG_LOAD, previousForView);
}
- mRequests.remove(view);
+
+ Loadable loadable = new Loadable(mContext, iconView, fso);
+ mRequests.put(iconView, loadable);
+ iconView.setImageDrawable(defaultIcon);
+
+ mWorkerHandler.obtainMessage(MSG_LOAD, loadable).sendToTarget();
}
private class WorkerHandler extends Handler {
@@ -215,115 +329,13 @@ public class IconHolder {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LOAD:
- FileSystemObject fso = (FileSystemObject) msg.obj;
- Drawable d = loadDrawable(fso);
- if (d != null) {
- LoadResult result = new LoadResult();
- result.fso = fso;
- result.result = d;
- mHandler.obtainMessage(MSG_LOADED, result).sendToTarget();
+ Loadable l = (Loadable) msg.obj;
+ if (l.load()) {
+ mHandler.obtainMessage(MSG_LOADED, l).sendToTarget();
}
break;
}
}
-
- private Drawable loadDrawable(FileSystemObject fso) {
- final String filePath = MediaHelper.normalizeMediaPath(fso.getFullPath());
-
- if (KnownMimeTypeResolver.isAndroidApp(mContext, fso)) {
- return getAppDrawable(fso);
- } else if (KnownMimeTypeResolver.isImage(mContext, fso)) {
- return getImageDrawable(filePath);
- } else if (KnownMimeTypeResolver.isVideo(mContext, fso)) {
- return getVideoDrawable(filePath);
- } else if (FileHelper.isDirectory(fso)) {
- synchronized (mMediaObserver) {
- if (mNeedAlbumUpdate) {
- mNeedAlbumUpdate = false;
- mAlbums = MediaHelper.getAllAlbums(mContext.getContentResolver());
- }
- }
- if (mAlbums.containsKey(filePath)) {
- return getAlbumDrawable(mAlbums.get(filePath));
- }
- }
-
- return null;
- }
-
- /**
- * Method that returns the main icon of the app
- *
- * @param fso The FileSystemObject
- * @return Drawable The drawable or null if cannot be extracted
- */
- private Drawable getAppDrawable(FileSystemObject fso) {
- final String filepath = fso.getFullPath();
- PackageManager pm = mContext.getPackageManager();
- PackageInfo packageInfo = pm.getPackageArchiveInfo(filepath,
- PackageManager.GET_ACTIVITIES);
- if (packageInfo != null) {
- // Read http://code.google.com/p/android/issues/detail?id=9151, CM fixed this
- // issue. We retain it for compatibility with older versions and roms without
- // this fix. Required to access apk which are not installed.
- final ApplicationInfo appInfo = packageInfo.applicationInfo;
- appInfo.sourceDir = filepath;
- appInfo.publicSourceDir = filepath;
- return pm.getDrawable(appInfo.packageName, appInfo.icon, appInfo);
- }
- return null;
- }
-
- /**
- * Method that returns a thumbnail of the picture
- *
- * @param file The path to the file
- * @return Drawable The drawable or null if cannot be extracted
- */
- private Drawable getImageDrawable(String file) {
- Bitmap thumb = ThumbnailUtils.createImageThumbnail(
- MediaHelper.normalizeMediaPath(file),
- ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL);
- if (thumb == null) {
- return null;
- }
- return new BitmapDrawable(mContext.getResources(), thumb);
- }
-
- /**
- * Method that returns a thumbnail of the video
- *
- * @param file The path to the file
- * @return Drawable The drawable or null if cannot be extracted
- */
- private Drawable getVideoDrawable(String file) {
- Bitmap thumb = ThumbnailUtils.createVideoThumbnail(
- MediaHelper.normalizeMediaPath(file),
- ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL);
- if (thumb == null) {
- return null;
- }
- return new BitmapDrawable(mContext.getResources(), thumb);
- }
-
- /**
- * Method that returns a thumbnail of the album folder
- *
- * @param albumId The album identifier
- * @return Drawable The drawable or null if cannot be extracted
- */
- private Drawable getAlbumDrawable(long albumId) {
- String path = MediaHelper.getAlbumThumbnailPath(mContext.getContentResolver(), albumId);
- if (path == null) {
- return null;
- }
- Bitmap thumb = ThumbnailUtils.createImageThumbnail(path,
- ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL);
- if (thumb == null) {
- return null;
- }
- return new BitmapDrawable(mContext.getResources(), thumb);
- }
}
/**