Add new interface to MediaSet.
Change-Id: I2339a7b6a6d3ee0dceaca805c5dbd03731a8a7d0
diff --git a/new3d/src/com/android/gallery3d/data/ComboMediaSet.java b/new3d/src/com/android/gallery3d/data/ComboAlbumSet.java
similarity index 65%
rename from new3d/src/com/android/gallery3d/data/ComboMediaSet.java
rename to new3d/src/com/android/gallery3d/data/ComboAlbumSet.java
index 1df9b25..24147dc 100644
--- a/new3d/src/com/android/gallery3d/data/ComboMediaSet.java
+++ b/new3d/src/com/android/gallery3d/data/ComboAlbumSet.java
@@ -16,36 +16,23 @@
package com.android.gallery3d.data;
-// Merge multiple media sets into one.
-public class ComboMediaSet extends MediaSet {
-
+// Concatenate multiple media sets into one.
+// This only handles SubMediaSets, not MediaItems. (That's all we need now)
+public class ComboAlbumSet extends MediaSet implements MediaSet.MediaSetListener {
+ private static final String TAG = "ComboAlbumSet";
private final MediaSet[] mSets;
+ private long mUniqueId;
- public ComboMediaSet(MediaSet ... mediaSets) {
+ public ComboAlbumSet(long uniqueId, MediaSet ... mediaSets) {
+ mUniqueId = uniqueId;
mSets = mediaSets;
- }
-
- public MediaItem[] getCoverMediaItems() {
- throw new UnsupportedOperationException();
- }
-
- public MediaItem getMediaItem(int index) {
for (MediaSet set : mSets) {
- int size = set.getMediaItemCount();
- if (index < size) {
- return set.getMediaItem(index);
- }
- index -= size;
+ set.setContentListener(this);
}
- throw new IndexOutOfBoundsException();
}
- public int getMediaItemCount() {
- int count = 0;
- for (MediaSet set : mSets) {
- count += set.getMediaItemCount();
- }
- return count;
+ public long getId() {
+ return mUniqueId;
}
public MediaSet getSubMediaSet(int index) {
@@ -67,8 +54,8 @@
return count;
}
- public String getTitle() {
- return null;
+ public String getName() {
+ return TAG;
}
public int getTotalMediaItemCount() {
@@ -79,9 +66,15 @@
return count;
}
- public void setContentListener(MediaSetListener listener) {
+ public void reload() {
for (MediaSet set : mSets) {
- set.setContentListener(listener);
+ set.reload();
+ }
+ }
+
+ public void onContentChanged() {
+ if (mListener != null) {
+ mListener.onContentChanged();
}
}
}
diff --git a/new3d/src/com/android/gallery3d/data/DataManager.java b/new3d/src/com/android/gallery3d/data/DataManager.java
index 39296e4..9736493 100644
--- a/new3d/src/com/android/gallery3d/data/DataManager.java
+++ b/new3d/src/com/android/gallery3d/data/DataManager.java
@@ -23,6 +23,7 @@
import android.util.Log;
import com.android.gallery3d.app.GalleryContext;
+import com.android.gallery3d.util.IdentityCache;
import java.io.File;
import java.io.IOException;
@@ -32,13 +33,42 @@
private static int PICASA_CACHE_MAX_ENTRIES = 5000;
private static int PICASA_CACHE_MAX_BYTES = 200 * 1024 * 1024;
private static String PICASA_CACHE_FILE = "/picasaweb";
+
+ // Below are constants for categories.
+ public static final int ID_LOCAL_IMAGE = 1;
+ public static final int ID_LOCAL_VIDEO = 2;
+ public static final int ID_PICASA_IMAGE = 3;
+
+ public static final int ID_LOCAL_IMAGE_ALBUM = 4;
+ public static final int ID_LOCAL_VIDEO_ALBUM = 5;
+ public static final int ID_PICASA_ALBUM = 6;
+
+ public static final int ID_LOCAL_IMAGE_ALBUM_SET = 7;
+ public static final int ID_LOCAL_VIDEO_ALBUM_SET = 8;
+ public static final int ID_PICASA_ALBUM_SET = 9;
+
+ public static final int ID_COMBO_ALBUM_SET = 10;
+ public static final int ID_MERGE_LOCAL_ALBUM_SET = 11;
+ public static final int ID_MERGE_LOCAL_ALBUM = 12;
+
private GalleryContext mContext;
private MediaSet mRootSet;
private HandlerThread mDataThread;
+ private IdentityCache<Long, MediaItem> mMediaItemCache;
private BlobCache mPicasaCache = null;
public DataManager(GalleryContext context) {
mContext = context;
+ mMediaItemCache = new IdentityCache<Long, MediaItem>();
+ }
+
+ public static long makeId(int category, int item) {
+ long result = category;
+ return (result << 32) | item;
+ }
+
+ public static int extractItemId(long id) {
+ return (int) id;
}
// Return null when we cannot instantiate a BlobCache, e.g.:
@@ -70,10 +100,17 @@
public MediaSet getRootSet() {
if (mRootSet == null) {
PicasaAlbumSet picasaSet = new PicasaAlbumSet(mContext);
- LocalAlbumSet localSet = new LocalAlbumSet(mContext);
- picasaSet.invalidate();
+ LocalAlbumSet localImageSet = new LocalAlbumSet(mContext, true);
+ LocalAlbumSet localVideoSet = new LocalAlbumSet(mContext, false);
+ MediaSet localSet = new MergeAlbumSet(
+ makeId(ID_MERGE_LOCAL_ALBUM_SET, 0),
+ LocalAlbum.sDateTakenComparator,
+ localImageSet, localVideoSet);
- mRootSet = new ComboMediaSet(localSet, picasaSet);
+ mRootSet = new ComboAlbumSet(
+ makeId(ID_COMBO_ALBUM_SET, 0),
+ localSet, picasaSet);
+ mRootSet.reload();
}
return mRootSet;
}
@@ -82,6 +119,14 @@
return getRootSet().getSubMediaSet(subSetIndex);
}
+ public MediaItem getFromCache(Long key) {
+ return mMediaItemCache.get(key);
+ }
+
+ public MediaItem putToCache(long key, MediaItem item) {
+ return mMediaItemCache.put(Long.valueOf(key), item);
+ }
+
public synchronized Looper getDataLooper() {
if (mDataThread == null ) {
mDataThread = new HandlerThread(
diff --git a/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java b/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java
index e916bed..f9a66c5 100644
--- a/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java
+++ b/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.data;
+import android.content.ContentResolver;
import android.os.Handler;
import android.os.Message;
@@ -23,48 +24,35 @@
import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.util.Utils;
-import java.util.concurrent.atomic.AtomicInteger;
-
public abstract class DatabaseMediaSet extends MediaSet {
private static final int MSG_LOAD_DATABASE = 0;
private static final int MSG_UPDATE_CONTENT = 1;
- private static final int BIT_INVALIDATING = 1;
- private static final int BIT_PENDING = 2;
-
protected final Handler mMainHandler;
protected final Handler mDbHandler;
protected final GalleryContext mContext;
+ protected final ContentResolver mResolver;
- protected MediaSetListener mListener;
- private AtomicInteger mState = new AtomicInteger();
+ // How many times do we need to reload: 1 means we are reloading,
+ // 2 means after current reloading, we need to do another one.
+ private int mReloadCount;
protected DatabaseMediaSet(GalleryContext context) {
mContext = context;
+ mResolver = mContext.getContentResolver();
- mMainHandler = new Handler() {
+ mMainHandler = new SynchronizedHandler(context.getGLRootView()) {
@Override
public void handleMessage(Message message) {
Utils.Assert(message.what == MSG_UPDATE_CONTENT);
onUpdateContent();
if (mListener != null) mListener.onContentChanged();
- while (true) {
- int s = mState.get();
-
- // Either (1) resets the the pending bit and sets the
- // invalidating bit, or
- // (2) resets the state to 0 if the pending bit was
- // originally cleared.
- int t = (s & BIT_PENDING) == 0 ? 0 : BIT_INVALIDATING;
- if (mState.compareAndSet(s, t)) {
- if (t == BIT_INVALIDATING) {
- // Case 1: clear the pending bit by loading data
- // from database.
- mDbHandler.sendEmptyMessage(MSG_LOAD_DATABASE);
- }
- break;
+ synchronized (DatabaseMediaSet.this) {
+ // If we still have pending reload, do it now.
+ if (--mReloadCount > 0) {
+ mDbHandler.sendEmptyMessage(MSG_LOAD_DATABASE);
}
}
}
@@ -80,28 +68,15 @@
};
}
- public void invalidate() {
- while (true) {
- int s = mState.get();
-
- // State is moved either to (1) invalidating, or (2) invalidating and pending.
- int t = (s & BIT_INVALIDATING) == 0
- ? BIT_INVALIDATING
- : BIT_INVALIDATING | BIT_PENDING;
- if (mState.compareAndSet(s, t)) {
- if (t == BIT_INVALIDATING) {
- // Case 1: loading data from database.
- mDbHandler.sendEmptyMessage(MSG_LOAD_DATABASE);
- }
- break;
- }
+ public synchronized void reload() {
+ // If we already have reload pending, just return.
+ if (mReloadCount >= 2) return;
+ // If this is the first reload, start it.
+ if (++mReloadCount == 1) {
+ mDbHandler.sendEmptyMessage(MSG_LOAD_DATABASE);
}
}
- public void setContentListener(MediaSetListener listener) {
- mListener = listener;
- }
-
abstract protected void onLoadFromDatabase();
abstract protected void onUpdateContent();
}
diff --git a/new3d/src/com/android/gallery3d/data/LocalAlbum.java b/new3d/src/com/android/gallery3d/data/LocalAlbum.java
index 17a9e0e..a62e57c 100644
--- a/new3d/src/com/android/gallery3d/data/LocalAlbum.java
+++ b/new3d/src/com/android/gallery3d/data/LocalAlbum.java
@@ -18,117 +18,142 @@
import android.content.ContentResolver;
import android.database.Cursor;
+import android.net.Uri;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Video;
+import android.provider.MediaStore.Images.ImageColumns;
+import android.provider.MediaStore.Video.VideoColumns;
import com.android.gallery3d.app.GalleryContext;
import com.android.gallery3d.util.Utils;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Comparator;
-public class LocalAlbum extends DatabaseMediaSet {
- private static final int MAX_NUM_COVER_ITEMS = 4;
+public class LocalAlbum extends MediaSet {
+ private static final String TAG = "LocalAlbum";
+ private static final String[] COUNT_PROJECTION = { "count(*)" };
+ private final String mWhereClause;
+ private final String mOrderClause;
+ private final Uri mBaseUri;
+ private final String[] mProjection;
+ public static final Comparator<LocalAlbum> sBucketNameComparator =
+ new BucketNameComparator();
+ public static final Comparator<MediaItem> sDateTakenComparator =
+ new DateTakenComparator();
- public static final Comparator<LocalAlbum> sNameComparator = new MyComparator();
-
+ private final GalleryContext mContext;
+ private final ContentResolver mResolver;
private final int mBucketId;
- private final String mBucketTitle;
+ private final String mBucketName;
+ private boolean mIsImage;
+ private long mUniqueId;
- private final ArrayList<LocalMediaItem> mMediaItems =
- new ArrayList<LocalMediaItem>();
- private ArrayList<LocalMediaItem> mLoadBuffer =
- new ArrayList<LocalMediaItem>();
+ public LocalAlbum(GalleryContext context, int bucketId, String name, boolean isImage) {
+ mContext = context;
+ mResolver = context.getContentResolver();
+ mBucketId = bucketId;
+ mBucketName = name;
+ mIsImage = isImage;
- public LocalAlbum(GalleryContext context, int id, String title) {
- super(context);
- mBucketId = id;
- mBucketTitle= title;
- }
-
- public MediaItem[] getCoverMediaItems() {
- int size = Math.min(MAX_NUM_COVER_ITEMS, mMediaItems.size());
- MediaItem items[] = new MediaItem[size];
- for (int i = 0; i < size; ++i) {
- items[i] = mMediaItems.get(i);
+ if (isImage) {
+ mWhereClause = ImageColumns.BUCKET_ID + "=?";
+ mOrderClause = ImageColumns.DATE_TAKEN + " DESC, "
+ + ImageColumns._ID + " ASC";
+ mBaseUri = Images.Media.EXTERNAL_CONTENT_URI;
+ mProjection = LocalImage.PROJECTION;
+ mUniqueId = DataManager.makeId(
+ DataManager.ID_LOCAL_IMAGE_ALBUM, bucketId);
+ } else {
+ mWhereClause = VideoColumns.BUCKET_ID + "=?";
+ mOrderClause = VideoColumns.DATE_TAKEN + " DESC, "
+ + VideoColumns._ID + " ASC";
+ mBaseUri = Video.Media.EXTERNAL_CONTENT_URI;
+ mProjection = LocalVideo.PROJECTION;
+ mUniqueId = DataManager.makeId(
+ DataManager.ID_LOCAL_VIDEO_ALBUM, bucketId);
}
- return items;
}
- public MediaItem getMediaItem(int index) {
- return mMediaItems.get(index);
+ public long getId() {
+ return mUniqueId;
+ }
+
+ public ArrayList<MediaItem> getMediaItem(int start, int count) {
+ ImageService imageService = mContext.getImageService();
+ DataManager dataManager = mContext.getDataManager();
+
+ Uri uri = mBaseUri.buildUpon()
+ .appendQueryParameter("limit", start + "," + count).build();
+ ArrayList<MediaItem> list = new ArrayList<MediaItem>();
+ Cursor cursor = mResolver.query(
+ uri, mProjection, mWhereClause,
+ new String[]{String.valueOf(mBucketId)},
+ mOrderClause);
+
+ try {
+ while (cursor.moveToNext()) {
+ if (mIsImage) {
+ list.add(LocalImage.load(imageService, cursor, dataManager));
+ } else {
+ list.add(LocalVideo.load(imageService, cursor, dataManager));
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ return list;
}
public int getMediaItemCount() {
- return mMediaItems.size();
+ Cursor cursor = mResolver.query(
+ mBaseUri, COUNT_PROJECTION, mWhereClause,
+ new String[]{String.valueOf(mBucketId)}, null);
+ try {
+ Utils.Assert(cursor.moveToNext());
+ return cursor.getInt(0);
+ } finally {
+ cursor.close();
+ }
}
- public MediaSet getSubMediaSet(int index) {
- throw new IndexOutOfBoundsException();
- }
-
- public int getSubMediaSetCount() {
- return 0;
- }
-
- public String getTitle() {
- return mBucketTitle;
+ public String getName() {
+ return mBucketName;
}
public int getTotalMediaItemCount() {
- return mMediaItems.size();
+ return getMediaItemCount();
}
- @Override
- protected void onLoadFromDatabase() {
- ArrayList<LocalMediaItem> items = new ArrayList<LocalMediaItem>();
- mLoadBuffer = items;
-
- ContentResolver resolver = mContext.getContentResolver();
- ImageService imageService = mContext.getImageService();
-
- Cursor cursor = LocalImage.queryImageInBucket(resolver, mBucketId);
- try {
- while (cursor.moveToNext()) {
- items.add(LocalImage.load(imageService, cursor));
- }
- } finally {
- cursor.close();
- }
-
- cursor = LocalVideo.queryVideoInBucket(resolver, mBucketId);
- try {
- while (cursor.moveToNext()) {
- items.add(LocalVideo.load(imageService, cursor));
- }
- } finally {
- cursor.close();
- }
-
- Collections.sort(items, new Comparator<LocalMediaItem>() {
-
- public int compare(LocalMediaItem o1, LocalMediaItem o2) {
- // sort items in descending order based on their taken time.
- long result = -(o1.mDateTakenInMs - o2.mDateTakenInMs);
- return result == 0
- ? o1.mId - o2.mId
- : result > 0 ? 1 : -1;
- }
- });
- }
-
- @Override
- protected void onUpdateContent() {
- Utils.Assert(mLoadBuffer != null);
- mMediaItems.clear();
- mMediaItems.addAll(mLoadBuffer);
- mLoadBuffer = null;
- }
-
- private static class MyComparator implements Comparator<LocalAlbum> {
-
+ private static class BucketNameComparator implements Comparator<LocalAlbum> {
public int compare(LocalAlbum s1, LocalAlbum s2) {
- int result = s1.mBucketTitle.compareTo(s2.mBucketTitle);
- return result != 0 ? result : s1.mBucketId - s2.mBucketId;
+ int result = s1.mBucketName.compareTo(s2.mBucketName);
+ if (result != 0) return result;
+ if (s1.mBucketId > s2.mBucketId) {
+ return 1;
+ } else if (s1.mBucketId < s2.mBucketId) {
+ return -1;
+ } else {
+ return 0;
+ }
}
}
+
+ private static class DateTakenComparator implements Comparator<MediaItem> {
+ public int compare(MediaItem item1, MediaItem item2) {
+ LocalMediaItem s1 = (LocalMediaItem) item1;
+ LocalMediaItem s2 = (LocalMediaItem) item2;
+ if (s1.mDateTakenInMs > s2.mDateTakenInMs) {
+ return -1;
+ } else if (s1.mDateTakenInMs < s2.mDateTakenInMs) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ public void reload() {
+ // do nothing
+ }
}
diff --git a/new3d/src/com/android/gallery3d/data/LocalAlbumSet.java b/new3d/src/com/android/gallery3d/data/LocalAlbumSet.java
index 5ae40f3..7cab3f3 100644
--- a/new3d/src/com/android/gallery3d/data/LocalAlbumSet.java
+++ b/new3d/src/com/android/gallery3d/data/LocalAlbumSet.java
@@ -16,7 +16,6 @@
package com.android.gallery3d.data;
-import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore.Images;
@@ -32,11 +31,8 @@
import java.util.Map;
public class LocalAlbumSet extends DatabaseMediaSet {
- private static final String TITLE = "RootSet";
+ private static final String TAG = "LocalAlbumSet";
- // Must preserve order between these indices and the order of the terms in
- // BUCKET_PROJECTION_IMAGES, BUCKET_PROJECTION_VIDEOS.
- // Not using SortedHashMap for efficiency reasons.
private static final int BUCKET_ID_INDEX = 0;
private static final int BUCKET_NAME_INDEX = 1;
@@ -48,77 +44,61 @@
VideoColumns.BUCKET_ID,
VideoColumns.BUCKET_DISPLAY_NAME };
- private int mTotalCountCached = -1;
+ private final String[] mProjection;
+ private final Uri mBaseUri;
- private final ArrayList<LocalAlbum>
- mSubsets = new ArrayList<LocalAlbum>();
-
+ private boolean mIsImage;
+ private long mUniqueId;
+ private final ArrayList<LocalAlbum> mAlbums = new ArrayList<LocalAlbum>();
private HashMap<Integer, String> mLoadBuffer;
- public LocalAlbumSet(GalleryContext context) {
+ public LocalAlbumSet(GalleryContext context, boolean isImage) {
super(context);
- invalidate();
+ mIsImage = isImage;
+ if (isImage) {
+ mProjection = PROJECTION_IMAGE_BUCKETS;
+ mBaseUri = Images.Media.EXTERNAL_CONTENT_URI;
+ mUniqueId = DataManager.makeId(DataManager.ID_LOCAL_IMAGE_ALBUM_SET, 0);
+ } else {
+ mProjection = PROJECTION_VIDEO_BUCKETS;
+ mBaseUri = Video.Media.EXTERNAL_CONTENT_URI;
+ mUniqueId = DataManager.makeId(DataManager.ID_LOCAL_VIDEO_ALBUM_SET, 0);
+ }
}
- public MediaItem[] getCoverMediaItems() {
- return new MediaItem[0];
- }
-
- public MediaItem getMediaItem(int index) {
- throw new IndexOutOfBoundsException();
- }
-
- public synchronized int getMediaItemCount() {
- return 0;
+ public long getId() {
+ return mUniqueId;
}
public synchronized MediaSet getSubMediaSet(int index) {
- return mSubsets.get(index);
+ return mAlbums.get(index);
}
public synchronized int getSubMediaSetCount() {
- return mSubsets.size();
+ return mAlbums.size();
}
- public String getTitle() {
- return TITLE;
+ public String getName() {
+ return TAG;
}
public int getTotalMediaItemCount() {
- if (mTotalCountCached >= 0) return mTotalCountCached;
int total = 0;
- for (MediaSet subset : mSubsets) {
- total += subset.getTotalMediaItemCount();
+ for (MediaSet album : mAlbums) {
+ total += album.getTotalMediaItemCount();
}
- mTotalCountCached = total;
return total;
}
@Override
protected void onLoadFromDatabase() {
-
- ContentResolver resolver = mContext.getContentResolver();
HashMap<Integer, String> map = new HashMap<Integer, String>();
mLoadBuffer = map;
- Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI.buildUpon().
+ Uri uri = mBaseUri.buildUpon().
appendQueryParameter("distinct", "true").build();
- Cursor cursor = resolver.query(
- uriImages, PROJECTION_IMAGE_BUCKETS, null, null, null);
- if (cursor == null) throw new NullPointerException();
- try {
- while (cursor.moveToNext()) {
- map.put(cursor.getInt(BUCKET_ID_INDEX),
- cursor.getString(BUCKET_NAME_INDEX));
- }
- } finally {
- cursor.close();
- }
-
- Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI.buildUpon().
- appendQueryParameter("distinct", "true").build();
- cursor = resolver.query(
- uriVideos, PROJECTION_VIDEO_BUCKETS, null, null, null);
+ Cursor cursor = mResolver.query(
+ uri, mProjection, null, null, null);
if (cursor == null) throw new NullPointerException();
try {
while (cursor.moveToNext()) {
@@ -135,17 +115,12 @@
HashMap<Integer, String> map = mLoadBuffer;
if (map == null) throw new IllegalStateException();
- GalleryContext context = mContext;
for (Map.Entry<Integer, String> entry : map.entrySet()) {
- mSubsets.add(new LocalAlbum(
- context, entry.getKey(), entry.getValue()));
+ mAlbums.add(new LocalAlbum(
+ mContext, entry.getKey(), entry.getValue(), mIsImage));
}
mLoadBuffer = null;
- Collections.sort(mSubsets, LocalAlbum.sNameComparator);
-
- for (LocalAlbum mediaset : mSubsets) {
- mediaset.invalidate();
- }
+ Collections.sort(mAlbums, LocalAlbum.sBucketNameComparator);
}
}
diff --git a/new3d/src/com/android/gallery3d/data/LocalImage.java b/new3d/src/com/android/gallery3d/data/LocalImage.java
index 8f9636a..5481658 100644
--- a/new3d/src/com/android/gallery3d/data/LocalImage.java
+++ b/new3d/src/com/android/gallery3d/data/LocalImage.java
@@ -52,7 +52,7 @@
private static final int INDEX_DATA = 8;
private static final int INDEX_ORIENTATION = 9;
- private static final String[] PROJECTION_IMAGES = {
+ static final String[] PROJECTION = {
ImageColumns._ID, // 0
ImageColumns.TITLE, // 1
ImageColumns.MIME_TYPE, // 2
@@ -66,12 +66,17 @@
private final BitmapFactory.Options mOptions = new BitmapFactory.Options();
+ private long mUniqueId;
private int mRotation;
protected LocalImage(ImageService imageService) {
super(imageService);
}
+ public long getUniqueId() {
+ return mUniqueId;
+ }
+
protected Bitmap decodeImage(String path) throws IOException {
// TODO: need to figure out why simply setting JPEG_MARK_POSITION doesn't work!
BufferedInputStream bis = new BufferedInputStream(
@@ -140,10 +145,17 @@
}
}
- public static LocalImage load(ImageService imageService, Cursor cursor) {
- LocalImage item = new LocalImage(imageService);
+ public static LocalImage load(ImageService imageService, Cursor cursor,
+ DataManager dataManager) {
+ int itemId = cursor.getInt(INDEX_ID);
+ long uniqueId = DataManager.makeId(DataManager.ID_LOCAL_IMAGE, itemId);
+ LocalImage item = (LocalImage) dataManager.getFromCache(uniqueId);
+ if (item != null) return item;
- item.mId = cursor.getInt(INDEX_ID);
+ item = new LocalImage(imageService);
+ dataManager.putToCache(uniqueId, item);
+
+ item.mId = itemId;
item.mCaption = cursor.getString(INDEX_CAPTION);
item.mMimeType = cursor.getString(INDEX_MIME_TYPE);
item.mLatitude = cursor.getDouble(INDEX_LATITUDE);
@@ -153,20 +165,8 @@
item.mDateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
item.mFilePath = cursor.getString(INDEX_DATA);
item.mRotation = cursor.getInt(INDEX_ORIENTATION);
+ item.mUniqueId = uniqueId;
return item;
}
-
- public static Cursor queryImageInBucket(
- ContentResolver resolver, int bucketId) {
- // Build the where clause
- StringBuilder builder = new StringBuilder(ImageColumns.BUCKET_ID);
- builder.append(" = ").append(bucketId);
- String whereClause = builder.toString();
-
- return resolver.query(
- Images.Media.EXTERNAL_CONTENT_URI,
- PROJECTION_IMAGES, whereClause, null, null);
- }
-
}
diff --git a/new3d/src/com/android/gallery3d/data/LocalMediaItem.java b/new3d/src/com/android/gallery3d/data/LocalMediaItem.java
index 56ba886..3c1a0ca 100644
--- a/new3d/src/com/android/gallery3d/data/LocalMediaItem.java
+++ b/new3d/src/com/android/gallery3d/data/LocalMediaItem.java
@@ -29,7 +29,7 @@
//
public abstract class LocalMediaItem extends MediaItem {
- private static final String TAG = LocalMediaItem.class.getSimpleName();
+ private static final String TAG = "LocalMediaItem";
// database fields
protected int mId;
@@ -47,17 +47,12 @@
protected final ImageService mImageService;
- @SuppressWarnings("unchecked")
protected LocalMediaItem(ImageService imageService) {
mImageService = imageService;
mFutureBitmaps = new MyFuture[TYPE_COUNT];
mRequestId = new int[TYPE_COUNT];
}
- public String getTitle() {
- return mCaption;
- }
-
public synchronized Future<Bitmap>
requestImage(int type, FutureListener<? super Bitmap> listener) {
if (mFutureBitmaps[type] != null) {
@@ -111,5 +106,4 @@
cancelImageRequest(mSizeType);
}
}
-
}
diff --git a/new3d/src/com/android/gallery3d/data/LocalVideo.java b/new3d/src/com/android/gallery3d/data/LocalVideo.java
index 9bebcb4..2c317e2 100644
--- a/new3d/src/com/android/gallery3d/data/LocalVideo.java
+++ b/new3d/src/com/android/gallery3d/data/LocalVideo.java
@@ -21,9 +21,7 @@
import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.provider.MediaStore.Images;
import android.provider.MediaStore.Video;
-import android.provider.MediaStore.Images.ImageColumns;
import android.provider.MediaStore.Video.VideoColumns;
public class LocalVideo extends LocalMediaItem {
@@ -31,7 +29,7 @@
private static final int MICRO_TARGET_PIXELS = 128 * 128;
// Must preserve order between these indices and the order of the terms in
- // PROJECTION_VIDEOS.
+ // PROJECTION.
private static final int INDEX_ID = 0;
private static final int INDEX_CAPTION = 1;
private static final int INDEX_MIME_TYPE = 2;
@@ -43,7 +41,7 @@
private static final int INDEX_DATA = 8;
private static final int INDEX_DURATION = 9;
- private static final String[] PROJECTION_VIDEOS = new String[] {
+ static final String[] PROJECTION = new String[] {
VideoColumns._ID,
VideoColumns.TITLE,
VideoColumns.MIME_TYPE,
@@ -55,12 +53,17 @@
VideoColumns.DATA,
VideoColumns.DURATION};
+ private long mUniqueId;
public int mDurationInSec;
protected LocalVideo(ImageService imageService) {
super(imageService);
}
+ public long getUniqueId() {
+ return mUniqueId;
+ }
+
@Override
protected void cancelImageGeneration(ContentResolver resolver, int type) {
Video.Thumbnails.cancelThumbnailRequest(resolver, mId);
@@ -74,10 +77,10 @@
case TYPE_FULL_IMAGE:
case TYPE_THUMBNAIL:
return Video.Thumbnails.getThumbnail(
- resolver, mId, Images.Thumbnails.MINI_KIND, null);
+ resolver, mId, Video.Thumbnails.MINI_KIND, null);
case TYPE_MICROTHUMBNAIL:
Bitmap bitmap = Video.Thumbnails.getThumbnail(
- resolver, mId, Images.Thumbnails.MINI_KIND, null);
+ resolver, mId, Video.Thumbnails.MINI_KIND, null);
return bitmap == null
? null
: Utils.resize(bitmap, MICRO_TARGET_PIXELS);
@@ -86,8 +89,15 @@
}
}
- public static LocalVideo load(ImageService imageService, Cursor cursor) {
- LocalVideo item = new LocalVideo(imageService);
+ public static LocalVideo load(ImageService imageService, Cursor cursor,
+ DataManager dataManager) {
+ int itemId = cursor.getInt(INDEX_ID);
+ long uniqueId = DataManager.makeId(DataManager.ID_LOCAL_VIDEO, itemId);
+ LocalVideo item = (LocalVideo) dataManager.getFromCache(uniqueId);
+ if (item != null) return item;
+
+ item = new LocalVideo(imageService);
+ dataManager.putToCache(uniqueId, item);
item.mId = cursor.getInt(INDEX_ID);
item.mCaption = cursor.getString(INDEX_CAPTION);
@@ -99,22 +109,8 @@
item.mDateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
item.mFilePath = cursor.getString(INDEX_DATA);
item.mDurationInSec = cursor.getInt(INDEX_DURATION);
+ item.mUniqueId = uniqueId;
return item;
}
-
- public static Cursor queryVideoInBucket(
- ContentResolver resolver, int bucketId) {
-
- // Build the where clause
- StringBuilder builder = new StringBuilder(ImageColumns.BUCKET_ID);
- builder.append(" = ").append(bucketId);
- String whereClause = builder.toString();
-
- return resolver.query(
- Video.Media.EXTERNAL_CONTENT_URI,
- PROJECTION_VIDEOS, whereClause, null, null);
- }
-
-
}
diff --git a/new3d/src/com/android/gallery3d/data/MediaItem.java b/new3d/src/com/android/gallery3d/data/MediaItem.java
index 703cf16..d4a4d6b 100644
--- a/new3d/src/com/android/gallery3d/data/MediaItem.java
+++ b/new3d/src/com/android/gallery3d/data/MediaItem.java
@@ -31,8 +31,7 @@
public static final int IMAGE_WAIT = 1;
public static final int IMAGE_ERROR = -1;
- public abstract String getTitle();
-
+ public abstract long getUniqueId();
public abstract Future<Bitmap>
requestImage(int type, FutureListener<? super Bitmap> listener);
}
diff --git a/new3d/src/com/android/gallery3d/data/MediaSet.java b/new3d/src/com/android/gallery3d/data/MediaSet.java
index 319ffe4..176edeb 100644
--- a/new3d/src/com/android/gallery3d/data/MediaSet.java
+++ b/new3d/src/com/android/gallery3d/data/MediaSet.java
@@ -16,52 +16,68 @@
package com.android.gallery3d.data;
-// This is currently implemented MediaSet and MediaItem:
-//
-// | Local | Picasa
-// ----------+----------------
-// AlbumSet | 1 | 2
-// Album | 3 | 4
-// Image | 5 | 6
-// Video | 7 | (unimplemented)
-//
-// Inheritance relation:
-//
-// MediaSet -- DatabaseMediaSet -- {1,2,3,4}
-// MediaItem -- LocalMediaItem -- {5, 7}
-// -- {6}
-//
-// root = ComboMediaSet (LocalAlbumSet, PicasaAlbumSet);
-
+import java.util.ArrayList;
// MediaSet is a directory-like data structure.
// It contains MediaItems and sub-MediaSets.
//
// getTotalMediaItemCount() returns the number of all MediaItems, including
// those in sub-MediaSets.
-//
-// getCoverMediaItems() return a few representative MediaItems for this
-// MediaSet.
-//
public abstract class MediaSet {
public interface MediaSetListener {
public void onContentChanged();
}
- public abstract int getMediaItemCount();
+ public int getMediaItemCount() {
+ return 0;
+ }
- public abstract MediaItem getMediaItem(int index);
+ public ArrayList<MediaItem> getMediaItem(int start, int count) {
+ throw new IndexOutOfBoundsException();
+ }
- public abstract int getSubMediaSetCount();
+ // This is for compatibility only.
+ public MediaItem getMediaItem(int index) {
+ ArrayList<MediaItem> items = getMediaItem(index, 1);
+ if (items.size() > 0) {
+ return items.get(0);
+ } else {
+ return null;
+ }
+ }
- public abstract MediaSet getSubMediaSet(int index);
+ // This is for compatibility only.
+ public MediaItem[] getCoverMediaItems() {
+ if (getMediaItemCount() > 0) {
+ ArrayList<MediaItem> items = getMediaItem(0, 4);
+ MediaItem result[] = new MediaItem[items.size()];
+ return items.toArray(result);
+ } else if (getSubMediaSetCount() > 0) {
+ return getSubMediaSet(0).getCoverMediaItems();
+ } else {
+ return new MediaItem[0];
+ }
+ }
+
+ public int getSubMediaSetCount() {
+ return 0;
+ }
+
+ public MediaSet getSubMediaSet(int index) {
+ throw new IndexOutOfBoundsException();
+ }
public abstract int getTotalMediaItemCount();
- public abstract String getTitle();
+ public abstract long getId();
+ public abstract String getName();
- public abstract MediaItem[] getCoverMediaItems();
+ protected MediaSetListener mListener;
- public abstract void setContentListener(MediaSetListener listener);
+ public void setContentListener(MediaSetListener listener) {
+ mListener = listener;
+ }
+
+ public abstract void reload();
}
diff --git a/new3d/src/com/android/gallery3d/data/MergeAlbum.java b/new3d/src/com/android/gallery3d/data/MergeAlbum.java
new file mode 100644
index 0000000..75e2a8a
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/data/MergeAlbum.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2010 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.gallery3d.data;
+
+import android.util.Log;
+
+import java.util.Comparator;
+import java.util.TreeMap;
+import java.util.ArrayList;
+import java.util.SortedMap;
+
+// Merge two MediaSets.
+// This only handles MediaItems, not SubMediaSets.
+public class MergeAlbum extends MediaSet implements MediaSet.MediaSetListener {
+ private static final String TAG = "MergeAlbum";
+ private final long mUniqueId;
+ private final int mPageSize;
+ private final Comparator<MediaItem> mComparator;
+ private final MediaSet[] mSets;
+ private final int mSize; // caches mSets.length
+ private FetchCache[] mFetcher;
+
+ // mIndex maps global position to the position of each underlying media sets.
+ private TreeMap<Integer, int[]> mIndex;
+
+ public MergeAlbum(long uniqueId, int pageSize, Comparator<MediaItem> comparator,
+ MediaSet[] mediaSets) {
+ mUniqueId = uniqueId;
+ mPageSize = pageSize;
+ mComparator = comparator;
+ mSets = mediaSets;
+ mSize = mSets.length;
+ mFetcher = new FetchCache[mSize];
+ for (int i = 0; i < mSize; i++) {
+ MediaSet s = mSets[i];
+ s.setContentListener(this);
+ mFetcher[i] = new FetchCache(s, mPageSize);
+ }
+ mIndex = new TreeMap<Integer, int[]>();
+ mIndex.put(0, new int[mSize]);
+ }
+
+ private void invalidateCache() {
+ for (int i = 0; i < mSize; i++) {
+ mFetcher[i].invalidate();
+ }
+ mIndex.clear();
+ mIndex.put(0, new int[mSize]);
+ }
+
+ public long getId() {
+ return mUniqueId;
+ }
+
+ public String getName() {
+ return TAG;
+ }
+
+ public int getMediaItemCount() {
+ return getTotalMediaItemCount();
+ }
+
+ public ArrayList<MediaItem> getMediaItem(int start, int count) {
+
+ // First find the nearest mark position <= start.
+ SortedMap<Integer, int[]> head = mIndex.headMap(start + 1);
+ int markPos = head.lastKey();
+ int[] subPos = (int []) head.get(markPos).clone();
+ MediaItem[] slot = new MediaItem[mSize];
+
+ // fill all slots
+ for (int i = 0; i < mSize; i++) {
+ slot[i] = mFetcher[i].getItem(subPos[i]);
+ }
+
+ ArrayList<MediaItem> result = new ArrayList<MediaItem>();
+
+ for (int i = markPos; i < start + count; i++) {
+ int k = -1; // k points to the best slot up to now.
+ for (int j = 0; j < mSize; j++) {
+ if (slot[j] != null) {
+ if (k == -1 || mComparator.compare(slot[j], slot[k]) < 0) {
+ k = j;
+ }
+ }
+ }
+
+ // If we don't have anything, all streams are exhausted.
+ if (k == -1) break;
+
+ // Pick the best slot and refill it.
+ subPos[k]++;
+ if (i >= start) {
+ result.add(slot[k]);
+ Log.v(TAG, "added " + ((LocalMediaItem)slot[k]).mDateTakenInMs + " for " + i);
+ }
+ slot[k] = mFetcher[k].getItem(subPos[k]);
+
+ // Periodically leave a mark in the index, so we can come back later.
+ if ((i + 1) % mPageSize == 0) {
+ mIndex.put(i + 1, (int[]) subPos.clone());
+ }
+ }
+
+ return result;
+ }
+
+ public int getTotalMediaItemCount() {
+ int count = 0;
+ for (MediaSet set : mSets) {
+ count += set.getTotalMediaItemCount();
+ }
+ return count;
+ }
+
+ public void reload() {
+ for (MediaSet set : mSets) {
+ set.reload();
+ }
+ }
+
+ public void onContentChanged() {
+ invalidateCache();
+ if (mListener != null) {
+ mListener.onContentChanged();
+ }
+ }
+}
+
+class FetchCache {
+ private static final String TAG = "FetchCache";
+ private MediaSet mBaseSet;
+ private int mPageSize;
+ private ArrayList<MediaItem> mCache;
+ private int mStartPos;
+
+ FetchCache(MediaSet baseSet, int pageSize) {
+ mBaseSet = baseSet;
+ mPageSize = pageSize;
+ }
+
+ void invalidate() {
+ mCache = null;
+ }
+
+ MediaItem getItem(int index) {
+ boolean needLoading = false;
+ if (mCache == null) {
+ needLoading = true;
+ } else if (index < mStartPos || index >= mStartPos + mPageSize) {
+ needLoading = true;
+ }
+
+ if (needLoading) {
+ mCache = mBaseSet.getMediaItem(index, mPageSize);
+ mStartPos = index;
+ }
+
+ if (index < mStartPos || index >= mStartPos + mCache.size()) {
+ return null;
+ }
+
+ return mCache.get(index - mStartPos);
+ }
+}
diff --git a/new3d/src/com/android/gallery3d/data/MergeAlbumSet.java b/new3d/src/com/android/gallery3d/data/MergeAlbumSet.java
new file mode 100644
index 0000000..a53eab9
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/data/MergeAlbumSet.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2010 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.gallery3d.data;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+
+// Merge two media sets into one.
+// If the two media sets have sub media sets with the same name,
+// they will be merged.
+public class MergeAlbumSet extends MediaSet implements MediaSet.MediaSetListener {
+ private static final String TAG = "MergeAlbumSet";
+ private static final int PAGE_SIZE = 100;
+ private final long mUniqueId;
+ private Comparator<MediaItem> mComparator;
+ private final MediaSet[] mSets;
+ private MediaSet[] mAlbums;
+
+ public MergeAlbumSet(long uniqueId, Comparator<MediaItem> comparator,
+ MediaSet ... mediaSets) {
+ mUniqueId = uniqueId;
+ mComparator = comparator;
+ mSets = mediaSets;
+ updateNames();
+ for (MediaSet set : mediaSets) {
+ set.setContentListener(this);
+ }
+ }
+
+ public long getId() {
+ return mUniqueId;
+ }
+
+ private void updateNames() {
+
+ // This map maps from a the item id to a list of media sets.
+ // The list of media sets are the media set with that item id.
+ TreeMap<Integer, ArrayList<MediaSet>> map =
+ new TreeMap<Integer, ArrayList<MediaSet>>();
+ for (MediaSet set : mSets) {
+ for (int i = 0, n = set.getSubMediaSetCount(); i < n; i++) {
+ MediaSet subset = set.getSubMediaSet(i);
+ int itemId = DataManager.extractItemId(subset.getId());
+ ArrayList<MediaSet> list = map.get(itemId);
+ if (list == null) {
+ list = new ArrayList<MediaSet>();
+ map.put(itemId, list);
+ }
+ list.add(subset);
+ }
+ }
+
+ int size = map.size();
+ mAlbums = new MediaSet[size];
+
+ int i = 0;
+ for (Map.Entry<Integer, ArrayList<MediaSet>> entry : map.entrySet()) {
+ ArrayList<MediaSet> list = entry.getValue();
+ if (list.size() == 1) {
+ mAlbums[i] = list.get(0);
+ } else {
+ int itemId = entry.getKey();
+ long id = DataManager.makeId(DataManager.ID_MERGE_LOCAL_ALBUM,
+ itemId);
+ MediaSet[] sets = new MediaSet[list.size()];
+ mAlbums[i] = new MergeAlbum(id, PAGE_SIZE, mComparator,
+ list.toArray(sets));
+ }
+ i = i + 1;
+ }
+ }
+
+ public MediaSet getSubMediaSet(int index) {
+ return mAlbums[index];
+ }
+
+ public int getSubMediaSetCount() {
+ return mAlbums.length;
+ }
+
+ public String getName() {
+ return TAG;
+ }
+
+ public int getTotalMediaItemCount() {
+ int count = 0;
+ for (MediaSet set : mSets) {
+ count += set.getTotalMediaItemCount();
+ }
+ return count;
+ }
+
+ public void reload() {
+ for (MediaSet set : mSets) {
+ set.reload();
+ }
+ }
+
+ public void onContentChanged() {
+ updateNames();
+ if (mListener != null) {
+ mListener.onContentChanged();
+ }
+ }
+}
diff --git a/new3d/src/com/android/gallery3d/data/PicasaAlbum.java b/new3d/src/com/android/gallery3d/data/PicasaAlbum.java
index 28a6ada..8784334 100644
--- a/new3d/src/com/android/gallery3d/data/PicasaAlbum.java
+++ b/new3d/src/com/android/gallery3d/data/PicasaAlbum.java
@@ -16,85 +16,94 @@
package com.android.gallery3d.data;
+import android.content.ContentResolver;
import android.database.Cursor;
+import android.net.Uri;
import com.android.gallery3d.app.GalleryContext;
import com.android.gallery3d.picasa.AlbumEntry;
import com.android.gallery3d.picasa.EntrySchema;
import com.android.gallery3d.picasa.PhotoEntry;
import com.android.gallery3d.picasa.PicasaContentProvider;
+import com.android.gallery3d.util.Utils;
import java.util.ArrayList;
-public class PicasaAlbum extends DatabaseMediaSet {
- private static final int MAX_COVER_COUNT = 4;
+public class PicasaAlbum extends MediaSet {
+ private static final String TAG = "PicasaAlbum";
private static final EntrySchema SCHEMA = PhotoEntry.SCHEMA;
- private static final String WHERECLAUSE = PhotoEntry.Columns.ALBUM_ID
+ private static final String WHERE_CLAUSE = PhotoEntry.Columns.ALBUM_ID
+ " = ?";
+ private static final String[] COUNT_PROJECTION = { "count(*)" };
private final AlbumEntry mData;
- private final ArrayList<PicasaImage> mPhotos = new ArrayList<PicasaImage>();
- private final ArrayList<PicasaImage> mLoadBuffer = new ArrayList<PicasaImage>();
+ private final ContentResolver mResolver;
+ private long mUniqueId;
+ private GalleryContext mContext;
public PicasaAlbum(GalleryContext context, AlbumEntry entry) {
- super(context);
+ mContext = context;
+ mResolver = context.getContentResolver();
mData = entry;
+ mUniqueId = DataManager.makeId(
+ DataManager.ID_PICASA_ALBUM, (int) entry.id);
}
- public MediaItem[] getCoverMediaItems() {
- int size = Math.min(MAX_COVER_COUNT, mPhotos.size());
- MediaItem items[] = new MediaItem[size];
- for (int i = 0; i < size; ++i) {
- items[i] = mPhotos.get(i);
- }
- return items;
+ public long getId() {
+ return mUniqueId;
}
- public MediaItem getMediaItem(int index) {
- return mPhotos.get(index);
- }
+ public ArrayList<MediaItem> getMediaItem(int start, int count) {
+ Uri uri = PicasaContentProvider.PHOTOS_URI.buildUpon()
+ .appendQueryParameter("limit", start + "," + count).build();
- public int getMediaItemCount() {
- return mPhotos.size();
- }
-
- public MediaSet getSubMediaSet(int index) {
- throw new IndexOutOfBoundsException();
- }
-
- public int getSubMediaSetCount() {
- return 0;
- }
-
- public String getTitle() {
- return null;
- }
-
- public int getTotalMediaItemCount() {
- return mPhotos.size();
- }
-
- @Override
- protected void onLoadFromDatabase() {
- Cursor cursor = mContext.getContentResolver().query(
- PicasaContentProvider.PHOTOS_URI,
- SCHEMA.getProjection(), WHERECLAUSE,
- new String[] {String.valueOf(mData.id)},
+ ArrayList<MediaItem> list = new ArrayList<MediaItem>();
+ Cursor cursor = mResolver.query(uri,
+ SCHEMA.getProjection(), WHERE_CLAUSE,
+ new String[]{String.valueOf(mData.id)},
PhotoEntry.Columns.DISPLAY_INDEX);
+
try {
while (cursor.moveToNext()) {
PhotoEntry entry = SCHEMA.cursorToObject(cursor, new PhotoEntry());
- mLoadBuffer.add(new PicasaImage(mContext, entry));
+ DataManager dataManager = mContext.getDataManager();
+ long uniqueId = DataManager.makeId(
+ DataManager.ID_PICASA_IMAGE, (int) entry.id);
+ MediaItem item = dataManager.getFromCache(uniqueId);
+ if (item == null) {
+ item = new PicasaImage(mContext, entry);
+ dataManager.putToCache(uniqueId, item);
+ }
+ list.add(item);
}
} finally {
cursor.close();
}
+ return list;
+ }
+
+ public int getMediaItemCount() {
+ Cursor cursor = mResolver.query(
+ PicasaContentProvider.PHOTOS_URI,
+ COUNT_PROJECTION, WHERE_CLAUSE,
+ new String[]{String.valueOf(mData.id)}, null);
+ try {
+ Utils.Assert(cursor.moveToNext());
+ return cursor.getInt(0);
+ } finally {
+ cursor.close();
+ }
}
- @Override
- protected void onUpdateContent() {
- mPhotos.clear();
- mPhotos.addAll(mLoadBuffer);
- mLoadBuffer.clear();
+ public String getName() {
+ return TAG;
+ }
+
+ public int getTotalMediaItemCount() {
+ return getMediaItemCount();
+ }
+
+ public void reload() {
+ // do nothing
}
}
diff --git a/new3d/src/com/android/gallery3d/data/PicasaAlbumSet.java b/new3d/src/com/android/gallery3d/data/PicasaAlbumSet.java
index a56378d..dc8c65c 100644
--- a/new3d/src/com/android/gallery3d/data/PicasaAlbumSet.java
+++ b/new3d/src/com/android/gallery3d/data/PicasaAlbumSet.java
@@ -26,28 +26,16 @@
import java.util.ArrayList;
public class PicasaAlbumSet extends DatabaseMediaSet {
+ private static final String TAG = "PicasaAlbumSet";
private final EntrySchema SCHEMA = AlbumEntry.SCHEMA;
private final ArrayList<PicasaAlbum> mAlbums = new ArrayList<PicasaAlbum>();
- private int mCachedTotalCount = -1;
private final ArrayList<PicasaAlbum> mLoadBuffer = new ArrayList<PicasaAlbum>();
public PicasaAlbumSet(GalleryContext context) {
super(context);
}
- public MediaItem[] getCoverMediaItems() {
- throw new UnsupportedOperationException();
- }
-
- public MediaItem getMediaItem(int index) {
- throw new IndexOutOfBoundsException();
- }
-
- public int getMediaItemCount() {
- return 0;
- }
-
public MediaSet getSubMediaSet(int index) {
return mAlbums.get(index);
}
@@ -56,24 +44,26 @@
return mAlbums.size();
}
- public String getTitle() {
- return null;
+ public String getName() {
+ return TAG;
+ }
+
+ public long getId() {
+ return DataManager.makeId(DataManager.ID_PICASA_ALBUM_SET, 0);
}
public int getTotalMediaItemCount() {
- if (mCachedTotalCount >= 0) return mCachedTotalCount;
int totalCount = 0;
for (PicasaAlbum album : mAlbums) {
totalCount += album.getTotalMediaItemCount();
}
- mCachedTotalCount = totalCount;
return totalCount;
}
@Override
protected void onLoadFromDatabase() {
mLoadBuffer.clear();
- Cursor cursor = mContext.getContentResolver().query(
+ Cursor cursor = mResolver.query(
PicasaContentProvider.ALBUMS_URI,
SCHEMA.getProjection(), null, null, null);
try {
@@ -91,9 +81,5 @@
mAlbums.clear();
mAlbums.addAll(mLoadBuffer);
mLoadBuffer.clear();
-
- for (PicasaAlbum album : mAlbums) {
- album.invalidate();
- }
}
}
diff --git a/new3d/src/com/android/gallery3d/data/PicasaImage.java b/new3d/src/com/android/gallery3d/data/PicasaImage.java
index 666d48b..f465a0e 100644
--- a/new3d/src/com/android/gallery3d/data/PicasaImage.java
+++ b/new3d/src/com/android/gallery3d/data/PicasaImage.java
@@ -40,15 +40,18 @@
private final GalleryContext mContext;
private final PhotoEntry mData;
private final BlobCache mPicasaCache;
+ private final long mUniqueId;
public PicasaImage(GalleryContext context, PhotoEntry entry) {
mContext = context;
mData = entry;
mPicasaCache = mContext.getDataManager().getPicasaCache();
+ mUniqueId = DataManager.makeId(
+ DataManager.ID_PICASA_IMAGE, (int) entry.id);
}
- public String getTitle() {
- return null;
+ public long getUniqueId() {
+ return mUniqueId;
}
public synchronized Future<Bitmap>
diff --git a/new3d/src/com/android/gallery3d/util/IdentityCache.java b/new3d/src/com/android/gallery3d/util/IdentityCache.java
new file mode 100644
index 0000000..321ca38
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/util/IdentityCache.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 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.gallery3d.util;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
+public class IdentityCache<K, V> {
+
+ private final HashMap<K, Entry<K, V>> mWeakMap =
+ new HashMap<K, Entry<K, V>>();
+ private ReferenceQueue<V> mQueue = new ReferenceQueue<V>();
+
+ public IdentityCache() {
+ }
+
+ private static class Entry<K, V> extends WeakReference<V> {
+ K mKey;
+
+ public Entry(K key, V value, ReferenceQueue<V> queue) {
+ super(value, queue);
+ mKey = key;
+ }
+ }
+
+ private void cleanUpWeakMap() {
+ Entry<K, V> entry = (Entry<K, V>) mQueue.poll();
+ while (entry != null) {
+ mWeakMap.remove(entry.mKey);
+ entry = (Entry<K, V>) mQueue.poll();
+ }
+ }
+
+ public synchronized V put(K key, V value) {
+ cleanUpWeakMap();
+ Entry<K, V> entry = mWeakMap.put(
+ key, new Entry<K, V>(key, value, mQueue));
+ return entry == null ? null : entry.get();
+ }
+
+ public synchronized V get(K key) {
+ cleanUpWeakMap();
+ Entry<K, V> entry = mWeakMap.get(key);
+ return entry == null ? null : entry.get();
+ }
+
+ public synchronized void clear() {
+ mWeakMap.clear();
+ mQueue = new ReferenceQueue<V>();
+ }
+}
diff --git a/new3d/tests/src/com/android/gallery3d/ui/GLRootMock.java b/new3d/tests/src/com/android/gallery3d/ui/GLRootMock.java
index db07e48..c83e943 100644
--- a/new3d/tests/src/com/android/gallery3d/ui/GLRootMock.java
+++ b/new3d/tests/src/com/android/gallery3d/ui/GLRootMock.java
@@ -33,4 +33,5 @@
public boolean hasStencil() { return true; }
public void lockRenderThread() {}
public void unlockRenderThread() {}
+ public void setContentPane(GLView content) {}
}
diff --git a/new3d/tests/src/com/android/gallery3d/ui/GLRootStub.java b/new3d/tests/src/com/android/gallery3d/ui/GLRootStub.java
index 955cc18..d6bc678 100644
--- a/new3d/tests/src/com/android/gallery3d/ui/GLRootStub.java
+++ b/new3d/tests/src/com/android/gallery3d/ui/GLRootStub.java
@@ -26,4 +26,5 @@
public boolean hasStencil() { return true; }
public void lockRenderThread() {}
public void unlockRenderThread() {}
+ public void setContentPane(GLView content) {}
}