Refactor the code.
Change-Id: Icc699cb284f3d6c58590a912d48cc0044e1047d6
diff --git a/new3d/src/com/android/gallery3d/data/BucketMediaSet.java b/new3d/src/com/android/gallery3d/data/BucketMediaSet.java
index f3cc6e1..7e9852c 100644
--- a/new3d/src/com/android/gallery3d/data/BucketMediaSet.java
+++ b/new3d/src/com/android/gallery3d/data/BucketMediaSet.java
@@ -4,73 +4,31 @@
import android.content.ContentResolver;
import android.database.Cursor;
-import android.os.Handler;
-import android.os.Message;
import com.android.gallery3d.app.GalleryContext;
-import com.android.gallery3d.ui.SynchronizedHandler;
+import com.android.gallery3d.ui.Util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-public class BucketMediaSet implements MediaSet {
+public class BucketMediaSet extends DatabaseMediaSet {
private static final int MAX_NUM_COVER_ITEMS = 4;
- private static final int MSG_LOAD_DATABASE = 1;
- private static final int MSG_UPDATE_BUCKET = 2;
-
public static final Comparator<BucketMediaSet> sNameComparator = new MyComparator();
private final int mBucketId;
private final String mBucketTitle;
+
private final ArrayList<DatabaseMediaItem> mMediaItems =
new ArrayList<DatabaseMediaItem>();
private ArrayList<DatabaseMediaItem> mLoadBuffer =
new ArrayList<DatabaseMediaItem>();
- private final Handler mHandler;
- private final Handler mMainHandler;
-
- private MediaSetListener mListener;
- private ImageService mImageService;
- private ContentResolver mContentResolver;
-
- protected void invalidate() {
- mHandler.sendEmptyMessage(MSG_LOAD_DATABASE);
- }
-
public BucketMediaSet(GalleryContext context, int id, String title) {
- mContentResolver = context.getContentResolver();
- mImageService = context.getImageService();
+ super(context);
mBucketId = id;
mBucketTitle= title;
-
- mHandler = new Handler(context.getDataManager().getDataLooper()) {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MSG_LOAD_DATABASE:
- loadMediaItemsFromDatabase();
- break;
- default: throw new IllegalArgumentException();
- }
- }
- };
-
- mMainHandler = new SynchronizedHandler(
- context.getUIMonitor(), context.getMainLooper()) {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MSG_UPDATE_BUCKET:
- updateContent();
- break;
- default: throw new IllegalArgumentException();
- }
- }
- };
-
}
public MediaItem[] getCoverMediaItems() {
@@ -106,20 +64,18 @@
return mMediaItems.size();
}
- public void setContentListener(MediaSetListener listener) {
- mListener = listener;
- }
-
- private void loadMediaItemsFromDatabase() {
+ @Override
+ protected void onLoadFromDatabase() {
ArrayList<DatabaseMediaItem> items = new ArrayList<DatabaseMediaItem>();
mLoadBuffer = items;
- ContentResolver resolver = mContentResolver;
+ ContentResolver resolver = mContext.getContentResolver();
+ ImageService imageService = mContext.getImageService();
Cursor cursor = ImageMediaItem.queryImageInBucket(resolver, mBucketId);
try {
while (cursor.moveToNext()) {
- items.add(ImageMediaItem.load(mImageService, cursor));
+ items.add(ImageMediaItem.load(imageService, cursor));
}
} finally {
cursor.close();
@@ -128,7 +84,7 @@
cursor = VideoMediaItem.queryVideoInBucket(resolver, mBucketId);
try {
while (cursor.moveToNext()) {
- items.add(VideoMediaItem.load(mImageService, cursor));
+ items.add(VideoMediaItem.load(imageService, cursor));
}
} finally {
cursor.close();
@@ -144,12 +100,11 @@
: result > 0 ? 1 : -1;
}
});
-
- mMainHandler.sendEmptyMessage(MSG_UPDATE_BUCKET);
}
- private void updateContent() {
- if (mLoadBuffer == null) throw new IllegalArgumentException();
+ @Override
+ protected void onUpdateContent() {
+ Util.Assert(mLoadBuffer != null);
mMediaItems.clear();
mMediaItems.addAll(mLoadBuffer);
diff --git a/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java b/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java
index 1e4eb5f..77e21e4 100644
--- a/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java
+++ b/new3d/src/com/android/gallery3d/data/DatabaseMediaSet.java
@@ -9,16 +9,22 @@
import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.ui.Util;
+import java.util.concurrent.atomic.AtomicInteger;
+
public abstract class DatabaseMediaSet implements MediaSet {
private static final int MSG_LOAD_DATABASE = 0;
private static final int MSG_UPDATE_CONTENT = 1;
- protected Handler mMainHandler;
- protected Handler mDbHandler;
+ 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 MediaSetListener mListener;
+ private AtomicInteger mState = new AtomicInteger();
protected DatabaseMediaSet(GalleryContext context) {
mContext = context;
@@ -30,6 +36,24 @@
Util.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;
+ }
+ }
}
};
@@ -44,7 +68,21 @@
}
public void invalidate() {
- mDbHandler.sendEmptyMessage(MSG_LOAD_DATABASE);
+ 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 void setContentListener(MediaSetListener listener) {
diff --git a/new3d/src/com/android/gallery3d/data/LocalMediaSet.java b/new3d/src/com/android/gallery3d/data/LocalMediaSet.java
deleted file mode 100644
index 4e398ab..0000000
--- a/new3d/src/com/android/gallery3d/data/LocalMediaSet.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.android.gallery3d.data;
-
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-//
-// LocalMediaSet is a MediaSet which is obtained from MediaProvider.
-// Each LocalMediaSet is identified by a bucket id.
-// It is populated by addMediaItem(MediaItem) and addSubMediaSet(LocalMediaSet).
-//
-// getSubMediaSetById(int setId) returns a sub-MediaSet given a bucket id.
-//
-public class LocalMediaSet implements MediaSet {
- public static final int ROOT_SET_ID = -1;
- private static final String TAG = "LocalMediaSet";
-
- private static final int MAX_NUM_COVERED_ITEMS = 4;
-
- private final ArrayList<LocalMediaSet> mSubMediaSets =
- new ArrayList<LocalMediaSet>();
- private final Map<Integer, Integer> mIdsToIndice =
- new HashMap<Integer, Integer>();
-
- private final ArrayList<MediaItem> mMediaItems = new ArrayList<MediaItem>();
-
- private final int mBucketId;
- private final String mTitle;
-
- public LocalMediaSet(int bucketId, String title) {
- mBucketId = bucketId;
- mTitle = title;
- }
-
- public int getBucketId() {
- return mBucketId;
- }
-
- public MediaItem[] getCoverMediaItems() {
- MediaItem[] coverItems = new MediaItem[MAX_NUM_COVERED_ITEMS];
- int filled = fillCoverMediaItems(coverItems, 0);
- if (filled < MAX_NUM_COVERED_ITEMS) {
- MediaItem[] result = new MediaItem[filled];
- System.arraycopy(coverItems, 0, result, 0, filled);
- return result;
- } else {
- return coverItems;
- }
- }
-
- private int fillCoverMediaItems(MediaItem[] items, int offset) {
- // Fill from my MediaItems.
- int size = Math.min(getMediaItemCount(), items.length - offset);
- for (int i = 0; i < size; ++i) {
- items[offset + i] = getMediaItem(i);
- }
- if (offset + size == items.length) return size;
-
- // Fill from sub-MediaSets.
- int n = getSubMediaSetCount();
- for (int i = 0; i < n; ++i) {
- size += mSubMediaSets.get(i).fillCoverMediaItems(items, offset + size);
- if (offset + size == items.length) break;
- }
-
- return size;
- }
-
- public MediaItem getMediaItem(int index) {
- return mMediaItems.get(index);
- }
-
- void addMediaItem(MediaItem item) {
- mMediaItems.add(item);
- }
-
- public MediaSet getSubMediaSetById(int setId) {
- Integer index = mIdsToIndice.get(setId);
- return index == null ? null
- : mSubMediaSets.get(index);
- }
-
- public int getSubMediaSetCount() {
- return mSubMediaSets.size();
- }
-
- public MediaSet getSubMediaSet(int index) {
- return mSubMediaSets.get(index);
- }
-
- public String getTitle() {
- return mTitle;
- }
-
- public int getMediaItemCount() {
- return mMediaItems.size();
- }
-
- public int getTotalMediaItemCount() {
- int totalItemCount = mMediaItems.size();
- for (LocalMediaSet set : mSubMediaSets) {
- totalItemCount += set.getTotalMediaItemCount();
- }
- return totalItemCount;
- }
-
- public void addSubMediaSet(LocalMediaSet set) {
- if (mSubMediaSets.add(set)) {
- mIdsToIndice.put(set.mBucketId, mSubMediaSets.size() - 1);
- }
- }
-
- /*
- * Only for checking LocalMediaSet's content.
- */
- public void printOut() {
- Log.i(TAG, "Media Set, numItems: " + mTitle + ", " + getTotalMediaItemCount());
-
- for (MediaItem item : mMediaItems) {
- Log.i(TAG, "Media title: " + item.getTitle());
- }
-
- for (LocalMediaSet set: mSubMediaSets) {
- set.printOut();
- }
- }
-
- public void setContentListener(MediaSetListener listener) {
- }
-}
diff --git a/new3d/src/com/android/gallery3d/data/RootMediaSet.java b/new3d/src/com/android/gallery3d/data/RootMediaSet.java
index 7d5e6ee..c73e5a8 100644
--- a/new3d/src/com/android/gallery3d/data/RootMediaSet.java
+++ b/new3d/src/com/android/gallery3d/data/RootMediaSet.java
@@ -5,8 +5,6 @@
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Video;
import android.provider.MediaStore.Images.ImageColumns;
@@ -14,19 +12,15 @@
import android.util.Log;
import com.android.gallery3d.app.GalleryContext;
-import com.android.gallery3d.ui.SynchronizedHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-public class RootMediaSet implements MediaSet{
+public class RootMediaSet extends DatabaseMediaSet {
private static final String TITLE = "RootSet";
- private static final int MSG_LOAD_DATA = 0;
- private static final int MSG_UPDATE_CONTENT = 0;
-
// 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.
@@ -48,44 +42,9 @@
private HashMap<Integer, String> mLoadBuffer;
- private final Handler mDataHandler;
- private final Handler mMainHandler;
-
- private final GalleryContext mContext;
- private MediaSetListener mListener;
-
public RootMediaSet(GalleryContext context) {
-
- mContext = context;
-
- mDataHandler = new Handler(context.getDataManager().getDataLooper()) {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MSG_LOAD_DATA:
- loadBucketsFromDatabase();
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
- };
-
- mMainHandler = new SynchronizedHandler(
- context.getUIMonitor(), context.getMainLooper()) {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MSG_UPDATE_CONTENT:
- updateContent();
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
- };
-
- mDataHandler.sendEmptyMessage(MSG_LOAD_DATA);
+ super(context);
+ invalidate();
}
public MediaItem[] getCoverMediaItems() {
@@ -122,11 +81,9 @@
return total;
}
- public void setContentListener(MediaSetListener listener) {
- mListener = listener;
- }
+ @Override
+ protected void onLoadFromDatabase() {
- private void loadBucketsFromDatabase() {
ContentResolver resolver = mContext.getContentResolver();
HashMap<Integer, String> map = new HashMap<Integer, String>();
mLoadBuffer = map;
@@ -161,11 +118,10 @@
} finally {
cursor.close();
}
-
- mMainHandler.sendEmptyMessage(MSG_UPDATE_CONTENT);
}
- private void updateContent() {
+ @Override
+ protected void onUpdateContent() {
HashMap<Integer, String> map = mLoadBuffer;
if (map == null) throw new IllegalStateException();
diff --git a/new3d/tests/src/com/android/gallery3d/data/LocalMediaSetTest.java b/new3d/tests/src/com/android/gallery3d/data/LocalMediaSetTest.java
deleted file mode 100644
index 7dca658..0000000
--- a/new3d/tests/src/com/android/gallery3d/data/LocalMediaSetTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.graphics.Bitmap;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-@SmallTest
-public class LocalMediaSetTest extends TestCase {
- private static final String TAG = "LocalMediaSetTest";
-
- public void testEmptySet() {
- LocalMediaSet s = new LocalMediaSet(42, "Empty Set");
- assertEquals(0, s.getMediaItemCount());
- assertEquals(0, s.getSubMediaSetCount());
- assertEquals(0, s.getTotalMediaItemCount());
- assertEquals("Empty Set", s.getTitle());
- assertEquals(0, s.getCoverMediaItems().length);
- assertNull(s.getSubMediaSetById(42));
- }
-
- private static class MyMediaItem implements MediaItem {
- public String getMediaUri() { return ""; }
- public String getTitle() { return ""; }
- public Bitmap getImage(int type) { return null; }
- public void setListener(MediaItemListener listener) {}
- public int requestImage(int type) {return 0;}
- public void cancelImageRequest(int type) {}
- }
-
- public void testOneItem() {
- LocalMediaSet s = new LocalMediaSet(1, "One Item Set");
- MediaItem item = new MyMediaItem();
- s.addMediaItem(item);
- assertEquals(1, s.getMediaItemCount());
- assertEquals(0, s.getSubMediaSetCount());
- assertEquals(1, s.getTotalMediaItemCount());
- assertSame(item, s.getCoverMediaItems()[0]);
- assertSame(item, s.getMediaItem(0));
- }
-
- public void testTwoItems() {
- LocalMediaSet s = new LocalMediaSet(2, "Two Items Set");
- MediaItem item1 = new MyMediaItem();
- MediaItem item2 = new MyMediaItem();
- s.addMediaItem(item1);
- s.addMediaItem(item2);
- assertEquals(2, s.getMediaItemCount());
- assertEquals(0, s.getSubMediaSetCount());
- assertEquals(2, s.getTotalMediaItemCount());
- assertTrue(s.getCoverMediaItems()[0] == item1
- || s.getCoverMediaItems()[0] == item2);
- }
-
- public void testEmptySubMediaSet() {
- LocalMediaSet s = new LocalMediaSet(3, "One Empty Sub-MediaSet");
- LocalMediaSet t = new LocalMediaSet(42, "Empty Set");
- s.addSubMediaSet(t);
- assertEquals(0, s.getMediaItemCount());
- assertEquals(1, s.getSubMediaSetCount());
- assertEquals(0, s.getTotalMediaItemCount());
- assertEquals("One Empty Sub-MediaSet", s.getTitle());
- assertEquals(0, s.getCoverMediaItems().length);
- assertSame(t, s.getSubMediaSet(0));
- assertSame(t, s.getSubMediaSetById(42));
- assertNull(s.getSubMediaSetById(0));
- assertEquals("Empty Set", t.getTitle());
- }
-
- public void testSubSubMediaSet() {
- LocalMediaSet s = new LocalMediaSet(0, "Set 0");
- LocalMediaSet s1 = new LocalMediaSet(1, "Set 1");
- LocalMediaSet s2 = new LocalMediaSet(2, "Set 2");
- MediaItem item = new MyMediaItem();
- s.addSubMediaSet(s1);
- assertEquals(0, s.getMediaItemCount());
- assertEquals(1, s.getSubMediaSetCount());
- assertEquals(0, s.getTotalMediaItemCount());
- assertEquals(0, s.getCoverMediaItems().length);
- assertSame(s1, s.getSubMediaSet(0));
- assertNull(s.getSubMediaSetById(0));
- assertSame(s1, s.getSubMediaSetById(1));
- assertNull(s.getSubMediaSetById(2));
- s1.addSubMediaSet(s2);
- assertEquals(0, s.getMediaItemCount());
- assertEquals(1, s.getSubMediaSetCount());
- assertEquals(0, s.getTotalMediaItemCount());
- assertEquals(0, s.getCoverMediaItems().length);
- assertSame(s1, s.getSubMediaSet(0));
- assertNull(s.getSubMediaSetById(0));
- assertSame(s1, s.getSubMediaSetById(1));
- assertNull(s.getSubMediaSetById(2));
- assertSame(s2, s1.getSubMediaSet(0));
- assertSame(s2, s1.getSubMediaSetById(2));
- s2.addMediaItem(item);
- assertEquals(0, s.getMediaItemCount());
- assertEquals(1, s.getSubMediaSetCount());
- assertEquals(1, s.getTotalMediaItemCount());
- assertEquals(1, s.getCoverMediaItems().length);
- assertSame(s1, s.getSubMediaSet(0));
- assertNull(s.getSubMediaSetById(0));
- assertSame(s1, s.getSubMediaSetById(1));
- assertNull(s.getSubMediaSetById(2));
- }
-
- //
- // [0] - [1]
- // - 2
- // - 3
- // - [4] - 5
- // - 6
- // - 7
- // - [8] - [9] - 10
- // - [11]
- //
- public void testMediaSetTree() {
- LocalMediaSet s0 = new LocalMediaSet(LocalMediaSet.ROOT_SET_ID, "Set 0");
- LocalMediaSet s1 = new LocalMediaSet(1, "Set 1");
- LocalMediaSet s4 = new LocalMediaSet(4, "Set 4");
- LocalMediaSet s8 = new LocalMediaSet(8, "Set 8");
- LocalMediaSet s9 = new LocalMediaSet(9, "Set 9");
- LocalMediaSet s11 = new LocalMediaSet(11, "Set 11");
- MediaItem t2 = new MyMediaItem();
- MediaItem t3 = new MyMediaItem();
- MediaItem t5 = new MyMediaItem();
- MediaItem t6 = new MyMediaItem();
- MediaItem t7 = new MyMediaItem();
- MediaItem t10 = new MyMediaItem();
-
- s0.addSubMediaSet(s1);
- s0.addMediaItem(t2);
- s0.addMediaItem(t3);
- s0.addSubMediaSet(s4);
- s4.addMediaItem(t5);
- s4.addMediaItem(t6);
- s4.addMediaItem(t7);
- s4.addSubMediaSet(s8);
- s8.addSubMediaSet(s9);
- s9.addMediaItem(t10);
- s8.addSubMediaSet(s11);
-
- LocalMediaSet s = s0;
-
- assertEquals(2, s.getMediaItemCount());
- assertEquals(2, s.getSubMediaSetCount());
- assertEquals(6, s.getTotalMediaItemCount());
- assertTrue(s.getCoverMediaItems().length > 0);
- assertSame(s1, s.getSubMediaSet(0));
- assertSame(s4, s.getSubMediaSet(1));
- assertSame(s1, s.getSubMediaSetById(1));
- assertSame(s4, s.getSubMediaSetById(4));
- assertNull(s.getSubMediaSetById(8));
- assertSame(s8, s4.getSubMediaSetById(8));
- assertNull(s.getSubMediaSetById(LocalMediaSet.ROOT_SET_ID));
-
- MediaItem[] m = s.getCoverMediaItems();
- for (int i = 0; i < m.length; i++) {
- assertTrue(m[i] == t2 || m[i] == t3 || m[i] == t5
- || m[i] == t6 || m[i] == t7 || m[i] == t10);
- for (int j = 0; j < i; j++) {
- assertNotSame(m[j], m[i]);
- }
- }
- }
-}