diff --git a/xl-image_utils-test_suite/lint.xml b/xl-image_utils-test_suite/lint.xml
deleted file mode 100644
index ee0eead..0000000
--- a/xl-image_utils-test_suite/lint.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/AdvancedMemoryCacherTests.java b/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/AdvancedMemoryCacherTests.java
index a12e165..d00560a 100644
--- a/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/AdvancedMemoryCacherTests.java
+++ b/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/AdvancedMemoryCacherTests.java
@@ -19,9 +19,11 @@
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
+import android.os.Build;
import android.test.AndroidTestCase;
public class AdvancedMemoryCacherTests extends AndroidTestCase {
+ private static final boolean SHOULD_RUN = Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT;
private AdvancedMemoryLRUCacher mMemCache;
private Bitmap.Config mBitmapConfig;
@@ -29,10 +31,16 @@ public class AdvancedMemoryCacherTests extends AndroidTestCase {
protected void setUp() throws Exception {
super.setUp();
- mMemCache = new AdvancedMemoryLRUCacher();
+ if (SHOULD_RUN) {
+ mMemCache = new AdvancedMemoryLRUCacher();
+ }
}
public void testClearingCache() {
+ if (!SHOULD_RUN) {
+ return;
+ }
+
assertEquals(0, mMemCache.getNumImagesInCache());
mMemCache.cacheBitmap(getBitmap(), new DecodeSignature("url1", 1, mBitmapConfig));
assertEquals(1, mMemCache.getNumImagesInCache());
@@ -44,6 +52,10 @@ public void testClearingCache() {
@SuppressLint("NewApi")
public void testGetBitmapAndLru() {
+ if (!SHOULD_RUN) {
+ return;
+ }
+
Bitmap bitmap = getBitmap();
mMemCache.cacheBitmap(bitmap, new DecodeSignature("url1", 1, mBitmapConfig));
mMemCache.cacheBitmap(bitmap, new DecodeSignature("url1", 2, mBitmapConfig));
diff --git a/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/DiskCacheTests.java b/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/DiskCacheTests.java
index 653a6eb..71e4026 100644
--- a/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/DiskCacheTests.java
+++ b/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/DiskCacheTests.java
@@ -1,78 +1,219 @@
package com.xtremelabs.imageutils;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.URL;
+
import android.graphics.Bitmap;
+import android.graphics.Point;
import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+import android.widget.ImageView;
+
+import com.xtremelabs.imageutils.DiskLRUCacher.FileFormatException;
+import com.xtremelabs.imageutils.ImageLoader.Options;
+import com.xtremelabs.imageutils.ImageLoader.Options.ScalingPreference;
+import com.xtremelabs.imageutils.NetworkToDiskInterface.ImageDownloadResult;
+import com.xtremelabs.imageutils.NetworkToDiskInterface.ImageDownloadResult.Result;
public class DiskCacheTests extends AndroidTestCase {
- private ImageSystemDiskCache mDiskCache;
+ private static final String IMAGE_URL = "http://placekitten.com/400/600";
+
+ private static final CacheRequest CACHE_REQUEST = new CacheRequest(IMAGE_URL);
+
+ private DiskCache mDiskCache;
@Override
protected void setUp() throws Exception {
super.setUp();
- mDiskCache = new DiskCache(getContext(), mImageDiskObserver) {
- };
+ if (mDiskCache == null)
+ mDiskCache = new DiskCache(getContext(), mImageDiskObserver);
+
+ mDiskCache.init();
}
-
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mDiskCache.clear();
+ }
+
public void testDownloadImageFromInputStream() {
- fail();
+ downloadImage();
}
public void testIsCached() {
- fail();
- }
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
- public void testGetSampleSize() {
- fail();
- }
+ downloadImage();
- public void testBumpOnDisk() {
- fail();
+ assertTrue(mDiskCache.isCached(CACHE_REQUEST));
}
public void testSetDiskCacheSize() {
- fail();
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
+
+ downloadImage();
+ populateImageDetails();
+
+ assertTrue(mDiskCache.isCached(CACHE_REQUEST));
+
+ mDiskCache.setDiskCacheSize(1);
+
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
+
+ downloadImage();
+ populateImageDetails();
+
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
+
+ mDiskCache.setDiskCacheSize(1 * 1024 * 1024);
+
+ downloadImage();
+ populateImageDetails();
+
+ assertTrue(mDiskCache.isCached(CACHE_REQUEST));
}
public void testGetImageDimensions() {
- fail();
+ assertNull(mDiskCache.getImageDimensions(CACHE_REQUEST));
+
+ downloadImage();
+ populateImageDetails();
+
+ assertNotNull(mDiskCache.getImageDimensions(CACHE_REQUEST));
}
public void testInvalidateUri() {
fail();
}
- public void testGetBitmapSynchronouslyFromDisk() {
- fail();
+ public void testJournalingLruEvictions() {
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
+
+ downloadImage();
+ populateImageDetails();
+
+ assertTrue(mDiskCache.isCached(CACHE_REQUEST));
+
+ mDiskCache = new DiskCache(mContext, mImageDiskObserver);
+ mDiskCache.setDiskCacheSizeWithoutClearing(1);
+ mDiskCache.init();
+
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
+ }
+
+ public void testGetSampleSize() {
+ assertEquals(-1, mDiskCache.getSampleSize(CACHE_REQUEST));
+
+ downloadImage();
+ populateImageDetails();
+
+ MoreAsserts.assertNotEqual(-1, mDiskCache.getSampleSize(CACHE_REQUEST));
+ }
+
+ public void testGetSampleSizeWithNoDetailsSaved() {
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
+
+ downloadImage();
+
+ Options options = new Options();
+ options.heightBounds = 300;
+ options.widthBounds = 200;
+ options.scalingPreference = ScalingPreference.MATCH_TO_SMALLER_DIMENSION;
+ CacheRequest cacheRequest = new CacheRequest(IMAGE_URL, getScalingInfo(null, options));
+ assertEquals(2, mDiskCache.getSampleSize(cacheRequest));
+
+ fail(); // TODO read comment in getSampleSize
+ }
+
+ public void testGetBitmapSynchronouslyFromDisk() throws FileNotFoundException, FileFormatException {
+ downloadImage();
+ populateImageDetails();
+
+ DecodeSignature decodeSignature = new DecodeSignature(IMAGE_URL, 1, null);
+ Bitmap bitmap = mDiskCache.getBitmapSynchronouslyFromDisk(CACHE_REQUEST, decodeSignature);
+ assertNotNull(bitmap);
}
public void testCalculateAndSaveImageDetails() {
- fail();
+ assertFalse(mDiskCache.isCached(CACHE_REQUEST));
+
+ downloadImage();
+
+ assertEquals(1, mDiskCache.getSampleSize(CACHE_REQUEST));
+
+ populateImageDetails();
+
+ Options options = new Options();
+ options.heightBounds = 300;
+ options.widthBounds = 200;
+ options.scalingPreference = ScalingPreference.MATCH_TO_SMALLER_DIMENSION;
+ CacheRequest cacheRequest = new CacheRequest(IMAGE_URL, getScalingInfo(null, options));
+ assertEquals(2, mDiskCache.getSampleSize(cacheRequest));
}
- public void testGetDetailsPrioritizable() {
- fail();
+ ScalingInfo getScalingInfo(ImageView imageView, final Options options) {
+ ScalingInfo scalingInfo = new ScalingInfo();
+ if (options.overrideSampleSize != null) {
+ scalingInfo.sampleSize = options.overrideSampleSize;
+ return scalingInfo;
+ }
+
+ Integer width = options.widthBounds;
+ Integer height = options.heightBounds;
+
+ if (options.autoDetectBounds && imageView != null) {
+ Point viewBounds = ViewDimensionsUtil.getImageViewDimensions(imageView);
+
+ width = getBounds(width, viewBounds.x);
+ height = getBounds(height, viewBounds.y);
+ }
+
+ scalingInfo.width = width;
+ scalingInfo.height = height;
+ return scalingInfo;
}
- public void testGetDecodePrioritizable() {
- fail();
+ private static Integer getBounds(Integer currentDimension, int viewDimension) {
+ if (viewDimension != -1) {
+ if (currentDimension == null) {
+ currentDimension = viewDimension;
+ } else {
+ currentDimension = Math.min(currentDimension, viewDimension);
+ }
+ }
+ return currentDimension;
+ }
+
+ private InputStream getInputStream() {
+ try {
+ return new URL(IMAGE_URL).openStream();
+ } catch (Exception e) {}
+ return null;
+ }
+
+ private void downloadImage() {
+ ImageDownloadResult result = mDiskCache.downloadImageFromInputStream(IMAGE_URL, getInputStream());
+ assertEquals(result.getResult(), Result.SUCCESS);
+ }
+
+ private void populateImageDetails() {
+ mDiskCache.cacheImageDetails(CACHE_REQUEST);
}
private final ImageDiskObserver mImageDiskObserver = new ImageDiskObserver() {
@Override
- public void onImageDetailsRetrieved(String uri) {
- }
+ public void onImageDetailsRetrieved(String uri) {}
@Override
- public void onImageDetailsRequestFailed(String uri, String errorMessage) {
- }
+ public void onImageDetailsRequestFailed(String uri, String errorMessage) {}
@Override
- public void onImageDecoded(DecodeSignature decodeSignature, Bitmap bitmap, ImageReturnedFrom returnedFrom) {
- }
+ public void onImageDecoded(DecodeSignature decodeSignature, Bitmap bitmap, ImageReturnedFrom returnedFrom) {}
@Override
- public void onImageDecodeFailed(DecodeSignature decodeSignature, String error) {
- }
+ public void onImageDecodeFailed(DecodeSignature decodeSignature, String error) {}
};
}
diff --git a/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/ImageSystemDatabaseTests.java b/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/ImageSystemDatabaseTests.java
index cfa002a..25aebd8 100644
--- a/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/ImageSystemDatabaseTests.java
+++ b/xl-image_utils-test_suite/src/com/xtremelabs/imageutils/ImageSystemDatabaseTests.java
@@ -1,6 +1,8 @@
package com.xtremelabs.imageutils;
+import android.os.SystemClock;
import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
import com.xtremelabs.imageutils.ImageSystemDatabase.ImageSystemDatabaseObserver;
@@ -15,8 +17,13 @@ protected void setUp() throws Exception {
super.setUp();
mDatabase = new ImageSystemDatabase(mDatabaseObserver);
- mDatabase.init(getContext());
+ mDatabase.init(mContext);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
mDatabase.clear();
+ super.tearDown();
}
public void testBeginWrite() {
@@ -39,6 +46,20 @@ public void testEndWrite() {
assertFalse(entry.hasDetails());
}
+ public void testBump() {
+ mDatabase.beginWrite(TEST_URI_1);
+ mDatabase.endWrite(TEST_URI_1);
+
+ ImageEntry entry = mDatabase.getEntry(TEST_URI_1);
+ long lastAccessedTime = entry.lastAccessedTime;
+
+ SystemClock.sleep(10);
+
+ mDatabase.bump(TEST_URI_1);
+
+ MoreAsserts.assertNotEqual(lastAccessedTime, entry.lastAccessedTime);
+ }
+
public void testWriteFailed() {
mDatabase.beginWrite(TEST_URI_1);
ImageEntry entry = mDatabase.getEntry(TEST_URI_1);
@@ -56,9 +77,13 @@ public void testHasDetails() {
int testSizeY = 10;
mDatabase.beginWrite(TEST_URI_1);
mDatabase.endWrite(TEST_URI_1);
- mDatabase.submitDetails(TEST_URI_1, new Dimensions(testSizeX, testSizeY));
ImageEntry entry = mDatabase.getEntry(TEST_URI_1);
+ assertFalse(entry.hasDetails());
+
+ mDatabase.submitDetails(TEST_URI_1, new Dimensions(testSizeX, testSizeY), 100L);
+
+ entry = mDatabase.getEntry(TEST_URI_1);
assertNotNull(entry);
assertTrue(entry.onDisk);
@@ -76,7 +101,11 @@ public void testClear() {
mDatabase.endWrite(TEST_URI_2);
mDatabase.endWrite(TEST_URI_3);
- mDatabase.submitDetails(TEST_URI_3, new Dimensions(0, 0));
+ mDatabase.submitDetails(TEST_URI_3, new Dimensions(0, 0), 100L);
+
+ assertNotNull(mDatabase.getEntry(TEST_URI_1));
+ assertNotNull(mDatabase.getEntry(TEST_URI_2));
+ assertNotNull(mDatabase.getEntry(TEST_URI_3));
mDatabase.clear();
@@ -85,12 +114,84 @@ public void testClear() {
assertNull(mDatabase.getEntry(TEST_URI_3));
}
- public void testStartupDataRecovery() {
+ public void testFileSize() {
+ mDatabase.beginWrite(TEST_URI_1);
+ mDatabase.beginWrite(TEST_URI_2);
+ mDatabase.beginWrite(TEST_URI_3);
+ mDatabase.endWrite(TEST_URI_1);
+ mDatabase.endWrite(TEST_URI_2);
+ mDatabase.endWrite(TEST_URI_3);
+
+ assertEquals(0, mDatabase.getTotalFileSize());
+
+ mDatabase.submitDetails(TEST_URI_1, new Dimensions(0, 0), 100L);
+ mDatabase.submitDetails(TEST_URI_2, new Dimensions(0, 0), 100L);
+ mDatabase.submitDetails(TEST_URI_3, new Dimensions(0, 0), 100L);
+
+ assertEquals(300, mDatabase.getTotalFileSize());
+
+ mDatabase.submitDetails(TEST_URI_3, new Dimensions(0, 0), 200L);
+
+ assertEquals(400, mDatabase.getTotalFileSize());
+ }
+
+ public void testNoImageOnDiskTriggerDownload() {
fail();
+ // should probably be somewhere else
+
+ /*
+ * 1. Stub out getBitmapSynchronouslyFromDisk to throw a FileNotFoundException.
+ *
+ * 2. Stub out the DiskCache interface with a method for "restart image load"
+ *
+ * 3. Put an entry in the database for the "fake" image we are decoding.
+ *
+ * 4. Create a decode prioritizable and synchronously call "execute" on it.
+ *
+ * 5. Assert true that the database has removed the row for our image.
+ *
+ * 6. Assert true that the "restart image load" method was called. -- This is not built out yet and may not be 100% correct.
+ */
}
public void testStartupDataRecoveryOrdering() {
- fail();
+ mDatabase.beginWrite(TEST_URI_1);
+ mDatabase.beginWrite(TEST_URI_2);
+ mDatabase.beginWrite(TEST_URI_3);
+
+ mDatabase.endWrite(TEST_URI_1);
+ mDatabase.endWrite(TEST_URI_2);
+ mDatabase.endWrite(TEST_URI_3);
+
+ mDatabase.close();
+
+ mDatabase = new ImageSystemDatabase(mDatabaseObserver);
+ mDatabase.init(mContext);
+
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_1);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_2);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_3);
+ assertNull(mDatabase.removeLRU());
+
+ mDatabase.beginWrite(TEST_URI_1);
+ mDatabase.beginWrite(TEST_URI_2);
+ mDatabase.beginWrite(TEST_URI_3);
+
+ mDatabase.endWrite(TEST_URI_1);
+ mDatabase.endWrite(TEST_URI_2);
+ mDatabase.endWrite(TEST_URI_3);
+
+ mDatabase.bump(TEST_URI_1);
+
+ mDatabase.close();
+
+ mDatabase = new ImageSystemDatabase(mDatabaseObserver);
+ mDatabase.init(mContext);
+
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_2);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_3);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_1);
+ assertNull(mDatabase.removeLRU());
}
public void testJournalingEvictionWithNoWrite() {
@@ -102,11 +203,17 @@ public void testJournalingEvictionWithNoWrite() {
assertFalse(entry.hasDetails());
assertEquals(TEST_URI_1, entry.uri);
+ mDatabase.close();
+
ImageSystemDatabase database = new ImageSystemDatabase(mDatabaseObserver);
entry = database.getEntry(TEST_URI_1);
assertNull(entry);
}
+ public void testJournalingData() {
+ fail(); // TODO make sure that data written is same as data read after re-start (seen it fail)
+ }
+
public void testJournalingEvictionsWithNoWrite() {
mDatabase.beginWrite(TEST_URI_1);
mDatabase.beginWrite(TEST_URI_2);
@@ -114,45 +221,75 @@ public void testJournalingEvictionsWithNoWrite() {
mDatabase.endWrite(TEST_URI_2);
+ ImageEntry entry1 = mDatabase.getEntry(TEST_URI_1);
+ ImageEntry entry2 = mDatabase.getEntry(TEST_URI_2);
+ ImageEntry entry3 = mDatabase.getEntry(TEST_URI_3);
+
+ assertNotNull(entry1);
+ assertNotNull(entry2);
+ assertNotNull(entry3);
+
mDatabase.close();
ImageSystemDatabase database = new ImageSystemDatabase(mDatabaseObserver);
- ImageEntry entry1 = database.getEntry(TEST_URI_1);
- ImageEntry entry2 = database.getEntry(TEST_URI_2);
- ImageEntry entry3 = database.getEntry(TEST_URI_3);
+ database.init(mContext);
+ entry1 = database.getEntry(TEST_URI_1);
+ entry2 = database.getEntry(TEST_URI_2);
+ entry3 = database.getEntry(TEST_URI_3);
assertNull(entry1);
assertNotNull(entry2);
assertNull(entry3);
}
- public void testJournalingWithDetailsRequest() {
- fail();
- }
+ public void testRemoveLRU() {
+ mDatabase.beginWrite(TEST_URI_1);
+ mDatabase.beginWrite(TEST_URI_2);
+ mDatabase.beginWrite(TEST_URI_3);
- public void testJournalingWithDetailsRequests() {
- fail();
- }
+ mDatabase.endWrite(TEST_URI_1);
+ mDatabase.endWrite(TEST_URI_2);
+ mDatabase.endWrite(TEST_URI_3);
- public void testJournalingLruEvictions() {
- fail();
- }
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_1);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_2);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_3);
+ assertNull(mDatabase.removeLRU());
- public void testDetailsOnDatabaseRecovery() {
- fail();
+ mDatabase.beginWrite(TEST_URI_1);
+ mDatabase.beginWrite(TEST_URI_2);
+ mDatabase.beginWrite(TEST_URI_3);
+
+ mDatabase.endWrite(TEST_URI_1);
+ mDatabase.endWrite(TEST_URI_2);
+ mDatabase.endWrite(TEST_URI_3);
+
+ mDatabase.bump(TEST_URI_1);
+
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_2);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_3);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_1);
+ assertNull(mDatabase.removeLRU());
}
- public void testNoEvictionsForIncompleteDownloads() {
- fail();
+ public void testNoLruEvictionsForIncompleteDownloads() {
+ mDatabase.beginWrite(TEST_URI_1);
+ mDatabase.beginWrite(TEST_URI_2);
+ mDatabase.beginWrite(TEST_URI_3);
+
+ mDatabase.endWrite(TEST_URI_2);
+ mDatabase.endWrite(TEST_URI_3);
+
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_2);
+ assertEquals(mDatabase.removeLRU().uri, TEST_URI_3);
+ assertNull(mDatabase.removeLRU());
}
private final ImageSystemDatabaseObserver mDatabaseObserver = new ImageSystemDatabaseObserver() {
@Override
- public void onDetailsRequired(String filename) {
- }
+ public void onDetailsRequired(String filename) {}
@Override
- public void onBadJournalEntry(String filename) {
- }
+ public void onBadJournalEntry(ImageEntry entry) {}
};
}
diff --git a/xl_image_utils_lib/project.properties b/xl_image_utils_lib/project.properties
index 36f1594..484dab0 100644
--- a/xl_image_utils_lib/project.properties
+++ b/xl_image_utils_lib/project.properties
@@ -11,5 +11,5 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
-target=android-15
+target=android-17
android.library=true
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/AsyncOperationsMaps.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/AsyncOperationsMaps.java
index 59592b6..5015841 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/AsyncOperationsMaps.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/AsyncOperationsMaps.java
@@ -214,7 +214,7 @@ public void transferOperation(String uri, RequestParameters requestParameters, I
case DEFAULT:
CacheRequest cacheRequest = requestParameters.cacheRequest;
int sampleSize = mObserver.getSampleSize(cacheRequest);
- DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, requestParameters.cacheRequest.getOptions().preferedConfig);
+ DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, requestParameters.cacheRequest.getOptions().preferredConfig);
registerDecodeRequest(cacheRequest, decodeSignature, imageCacherListener, requestParameters.imageReturnedFrom);
break;
@@ -396,7 +396,7 @@ private void cancelDecodePrioritizable(ImageCacherListener imageCacherListener)
private synchronized DecodeSignature getDecodeSignature(CacheRequest cacheRequest) {
int sampleSize = mObserver.getSampleSize(cacheRequest);
- return new DecodeSignature(cacheRequest.getUri(), sampleSize, cacheRequest.getOptions().preferedConfig);
+ return new DecodeSignature(cacheRequest.getUri(), sampleSize, cacheRequest.getOptions().preferredConfig);
}
static interface OperationsObserver {
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskCache.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskCache.java
index 63599b8..c9ec117 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskCache.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskCache.java
@@ -1,29 +1,45 @@
package com.xtremelabs.imageutils;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
import java.net.URISyntaxException;
+import java.util.Map;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import com.xtremelabs.imageutils.DiskLRUCacher.FileFormatException;
+import com.xtremelabs.imageutils.ImageSystemDatabase.ImageSystemDatabaseObserver;
import com.xtremelabs.imageutils.NetworkToDiskInterface.ImageDownloadResult.Result;
class DiskCache implements ImageSystemDiskCache {
+ private static final int MAX_PERMANENT_STORAGE_IMAGE_DIMENSIONS_CACHED = 25;
private final Context mContext;
private final ImageDiskObserver mImageDiskObserver;
+ private final Map mPermanentStorageMap = new LRUMap(34, MAX_PERMANENT_STORAGE_IMAGE_DIMENSIONS_CACHED);
private ImageSystemDatabase mImageSystemDatabase;
private FileSystemManager mFileSystemManager;
+ private long mMaxCacheSize = 50 * 1024 * 1024;
DiskCache(Context context, ImageDiskObserver imageDiskObserver) {
- mContext = context;
+ mContext = context.getApplicationContext();
mImageDiskObserver = imageDiskObserver;
+ mFileSystemManager = new FileSystemManager("img", mContext);
+ mImageSystemDatabase = new ImageSystemDatabase(mImageSystemDatabaseObserver);
}
-
+
+ void init() {
+ mImageSystemDatabase.init(mContext);
+ clearLRUFiles();
+ }
+
@Override
public ImageDownloadResult downloadImageFromInputStream(String uri, InputStream inputStream) {
ImageDownloadResult result;
@@ -34,6 +50,7 @@ public ImageDownloadResult downloadImageFromInputStream(String uri, InputStream
mFileSystemManager.loadStreamToFile(inputStream, imageEntry.getFileName());
mImageSystemDatabase.endWrite(uri);
result = new ImageDownloadResult(Result.SUCCESS);
+
} catch (IOException e) {
mImageSystemDatabase.writeFailed(uri);
result = new ImageDownloadResult(Result.FAILURE, "Failed to download image to disk! IOException caught. Error message: " + e.getMessage());
@@ -44,62 +61,232 @@ public ImageDownloadResult downloadImageFromInputStream(String uri, InputStream
@Override
public boolean isCached(CacheRequest cacheRequest) {
- // TODO Auto-generated method stub
- return false;
+ boolean isCached;
+ String uri = cacheRequest.getUri();
+ if (cacheRequest.isFileSystemRequest()) {
+ isCached = mPermanentStorageMap.get(uri) != null;
+ } else {
+ ImageEntry entry = mImageSystemDatabase.getEntry(uri);
+ isCached = entry != null && entry.onDisk;
+ }
+
+ return isCached;
}
@Override
- public int getSampleSize(CacheRequest imageRequest) {
- // TODO Auto-generated method stub
- return 0;
+ public int getSampleSize(CacheRequest cacheRequest) {
+ Dimensions dimensions = getImageDimensions(cacheRequest);
+ if (dimensions == null) {
+ return -1;
+ }
+
+ return SampleSizeCalculationUtility.calculateSampleSize(cacheRequest, dimensions);
}
@Override
public void bumpOnDisk(String uri) {
- // TODO Auto-generated method stub
-
+ mImageSystemDatabase.bump(uri);
}
@Override
public void setDiskCacheSize(long sizeInBytes) {
- // TODO Auto-generated method stub
-
+ mMaxCacheSize = sizeInBytes;
+ clearLRUFiles();
}
@Override
public Dimensions getImageDimensions(CacheRequest cacheRequest) {
- // TODO Auto-generated method stub
- return null;
+ String uri = cacheRequest.getUri();
+ Dimensions dimensions;
+ if (cacheRequest.isFileSystemRequest()) {
+ dimensions = mPermanentStorageMap.get(uri);
+ } else {
+ ImageEntry entry = mImageSystemDatabase.getEntry(uri);
+ dimensions = entry != null && entry.hasDetails() ? new Dimensions(entry.sizeX, entry.sizeY) : null;
+ }
+ return dimensions;
}
@Override
public void invalidateFileSystemUri(String uri) {
- // TODO Auto-generated method stub
-
+ // TODO WATCH OUT FOR SYNCHRONIZATION ISSUES, probably should go through same flow that for 2 identical requests
+ mPermanentStorageMap.remove(uri);
}
@Override
public Bitmap getBitmapSynchronouslyFromDisk(CacheRequest cacheRequest, DecodeSignature decodeSignature) throws FileNotFoundException, FileFormatException {
- // TODO Auto-generated method stub
- return null;
+ int sampleSize = decodeSignature.sampleSize;
+ Bitmap.Config bitmapConfig = decodeSignature.bitmapConfig;
+
+ File file = getFile(cacheRequest);
+ FileInputStream fileInputStream = new FileInputStream(file);
+
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inSampleSize = sampleSize;
+ opts.inPreferredConfig = bitmapConfig;
+
+ Bitmap bitmap = BitmapFactory.decodeStream(fileInputStream, null, opts);
+ if (fileInputStream != null) {
+ try {
+ fileInputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (bitmap == null) {
+ file.delete();
+ throw new FileFormatException();
+ }
+ return bitmap;
}
@Override
public void calculateAndSaveImageDetails(CacheRequest cacheRequest) throws URISyntaxException, FileNotFoundException {
- // TODO Auto-generated method stub
+ String uri = cacheRequest.getUri();
+ File file = getFile(cacheRequest);
+ Dimensions dimensions = getImageDimensionsFromDisk(file);
+
+ if (cacheRequest.isFileSystemRequest()) {
+ mPermanentStorageMap.put(uri, dimensions);
+ } else {
+ mImageSystemDatabase.submitDetails(uri, dimensions, file.length());
+ clearLRUFiles();
+ }
+ }
+
+ private void clearLRUFiles() {
+ while (mImageSystemDatabase.getTotalFileSize() > mMaxCacheSize) {
+ ImageEntry entry = mImageSystemDatabase.removeLRU();
+ mFileSystemManager.deleteFile(entry.getFileName());
+ }
+ }
+
+ private File getFile(CacheRequest cacheRequest) throws FileNotFoundException {
+ String uri = cacheRequest.getUri();
+ File file;
+ if (cacheRequest.isFileSystemRequest()) {
+ try {
+ file = new File(new URI(uri.replace(" ", "%20")).getPath());
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ throw new FileNotFoundException();
+ }
+ } else {
+ ImageEntry entry = mImageSystemDatabase.getEntry(uri);
+ if (entry == null)
+ throw new FileNotFoundException();
+ file = mFileSystemManager.getFile(entry.getFileName());
+ }
+ return file;
+ }
+
+ private static Dimensions getImageDimensionsFromDisk(File file) throws FileNotFoundException {
+ FileInputStream fileInputStream = null;
+ try {
+ fileInputStream = new FileInputStream(file);
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(fileInputStream, null, o);
+ return new Dimensions(o.outWidth, o.outHeight);
+
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ throw e;
+
+ } finally {
+ if (fileInputStream != null) {
+ try {
+ fileInputStream.close();
+ } catch (IOException e) {}
+ }
+ }
}
@Override
- public Prioritizable getDetailsPrioritizable(CacheRequest imageRequest) {
- // TODO Auto-generated method stub
- return null;
+ public Prioritizable getDetailsPrioritizable(final CacheRequest cacheRequest) {
+ return new DefaultPrioritizable(cacheRequest, new Request(cacheRequest.getUri())) {
+ @Override
+ public void execute() {
+ cacheImageDetails(cacheRequest);
+ }
+ };
+ }
+
+ void cacheImageDetails(CacheRequest cacheRequest) {
+ String uri = cacheRequest.getUri();
+ try {
+ calculateAndSaveImageDetails(cacheRequest);
+ mImageDiskObserver.onImageDetailsRetrieved(uri);
+
+ } catch (URISyntaxException e) {
+ mImageDiskObserver.onImageDetailsRequestFailed(uri, "URISyntaxException caught when attempting to retrieve image details. URI: " + uri);
+ } catch (FileNotFoundException e) {
+ mImageDiskObserver.onImageDetailsRequestFailed(uri, "Image file not found. URI: " + uri);
+ }
}
@Override
- public Prioritizable getDecodePrioritizable(CacheRequest cacheRequest, DecodeSignature decodeSignature, ImageReturnedFrom imageReturnedFrom) {
- // TODO Auto-generated method stub
- return null;
+ public Prioritizable getDecodePrioritizable(final CacheRequest cacheRequest, final DecodeSignature decodeSignature, final ImageReturnedFrom imageReturnedFrom) {
+ return new DefaultPrioritizable(cacheRequest, new Request(decodeSignature)) {
+ @Override
+ public void execute() {
+ boolean failed = false;
+ String errorMessage = null;
+ Bitmap bitmap = null;
+ try {
+ bitmap = getBitmapSynchronouslyFromDisk(cacheRequest, decodeSignature);
+
+ } catch (FileNotFoundException e) {
+ failed = true;
+ errorMessage = "FileNotFoundException -- Disk decode failed with error message: " + e.getMessage();
+
+ } catch (FileFormatException e) {
+ failed = true;
+ errorMessage = "FileFormatException -- Disk decode failed with error message: " + e.getMessage();
+ }
+
+ if (!failed) {
+ mImageDiskObserver.onImageDecoded(decodeSignature, bitmap, imageReturnedFrom);
+
+ } else if (cacheRequest.isFileSystemRequest()) {
+ mPermanentStorageMap.remove(decodeSignature.uri);
+ mImageDiskObserver.onImageDecodeFailed(decodeSignature, errorMessage);
+
+ } else {
+ try {
+ mFileSystemManager.deleteFile(getFile(cacheRequest));
+ } catch (FileNotFoundException e) {}
+ mImageSystemDatabase.deleteEntry(decodeSignature.uri);
+ mImageDiskObserver.onImageDecodeFailed(decodeSignature, errorMessage);
+ }
+ // TODO need to re-start entire process if image was supposed to be on disk but wasn't
+ }
+ };
+ }
+
+ private final ImageSystemDatabaseObserver mImageSystemDatabaseObserver = new ImageSystemDatabaseObserver() {
+
+ @Override
+ public void onDetailsRequired(String filename) {
+ cacheImageDetails(new CacheRequest(filename));
+ }
+
+ @Override
+ public void onBadJournalEntry(ImageEntry entry) {
+ mFileSystemManager.deleteFile(entry.getFileName());
+ }
+ };
+
+ /** ALL THE METHODS BELOW ARE FOR TESTING PURPOSES ONLY!!!! */
+
+ void clear() {
+ mImageSystemDatabase.clear();
+ mFileSystemManager.clearDirectory();
+ }
+
+ void setDiskCacheSizeWithoutClearing(long bytes) {
+ mMaxCacheSize = bytes;
}
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskLRUCacher.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskLRUCacher.java
index ddfeb30..ffd38f8 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskLRUCacher.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/DiskLRUCacher.java
@@ -280,9 +280,6 @@ private static Dimensions getImageDimensionsFromDisk(File file) throws FileNotFo
}
public static class FileFormatException extends Exception {
- /**
- *
- */
private static final long serialVersionUID = -2180782787028503586L;
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/DisplayUtility.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/DisplayUtility.java
index 02c4b42..ff34dea 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/DisplayUtility.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/DisplayUtility.java
@@ -16,35 +16,18 @@
package com.xtremelabs.imageutils;
-import android.annotation.SuppressLint;
import android.content.Context;
-import android.graphics.Point;
-import android.os.Build;
-import android.view.Display;
-import android.view.WindowManager;
+import android.util.DisplayMetrics;
class DisplayUtility {
- private volatile Dimensions displaySize;
+ private Dimensions dimensions;
- @SuppressLint("NewApi")
- @SuppressWarnings("deprecation")
public Dimensions getDisplaySize(Context applicationContext) {
- if (displaySize == null) {
- Display display = ((WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
-
- if (Build.VERSION.SDK_INT < 13) {
- // These method calls are used before API level 13.
- displaySize = new Dimensions(display.getWidth(), display.getHeight());
- } else {
- Point size = new Point();
- display.getSize(size);
- displaySize = new Dimensions(size.x, size.y);
- }
+ if (dimensions == null) {
+ DisplayMetrics metrics = applicationContext.getResources().getDisplayMetrics();
+ dimensions = new Dimensions(metrics.widthPixels, metrics.heightPixels);
}
- return displaySize;
- }
- public void notifyConfigurationChanged() {
- displaySize = null;
+ return dimensions;
}
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/FileSystemManager.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/FileSystemManager.java
index c48610c..81982a7 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/FileSystemManager.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/FileSystemManager.java
@@ -134,6 +134,10 @@ private void deleteDirectory(File directory) {
public void deleteFile(String name) {
File file = getFile(name);
+ deleteFile(file);
+ }
+
+ public void deleteFile(File file) {
if (!file.isDirectory()) {
file.delete();
} else {
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageCacher.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageCacher.java
index 930c651..c4e03c9 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageCacher.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageCacher.java
@@ -80,7 +80,7 @@ public ImageResponse getBitmap(CacheRequest cacheRequest, ImageCacherListener im
boolean isCached = mDiskCache.isCached(cacheRequest);
if (isCached && sampleSize != -1) {
Bitmap bitmap;
- DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, cacheRequest.getOptions().preferedConfig);
+ DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, cacheRequest.getOptions().preferredConfig);
bitmap = mMemoryCache.getBitmap(decodeSignature);
if (bitmap != null)
return new ImageResponse(bitmap, ImageReturnedFrom.MEMORY, ImageResponseStatus.SUCCESS);
@@ -118,7 +118,7 @@ public ImageResponse getBitmapSynchronouslyFromDiskOrMemory(CacheRequest cacheRe
try {
if (isCached && sampleSize != -1) {
- DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, cacheRequest.getOptions().preferedConfig);
+ DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, cacheRequest.getOptions().preferredConfig);
Bitmap bitmap;
if ((bitmap = mMemoryCache.getBitmap(decodeSignature)) != null) {
return new ImageResponse(bitmap, ImageReturnedFrom.MEMORY, ImageResponseStatus.SUCCESS);
@@ -129,7 +129,7 @@ public ImageResponse getBitmapSynchronouslyFromDiskOrMemory(CacheRequest cacheRe
mDiskCache.calculateAndSaveImageDetails(cacheRequest);
sampleSize = getSampleSize(cacheRequest);
if (sampleSize != -1) {
- DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, cacheRequest.getOptions().preferedConfig);
+ DecodeSignature decodeSignature = new DecodeSignature(uri, sampleSize, cacheRequest.getOptions().preferredConfig);
return getBitmapSynchronouslyFromDisk(cacheRequest, decodeSignature);
}
}
@@ -342,14 +342,14 @@ protected Void doInBackground(Void... params) {
return null;
}
- DecodeSignature decodeSignature = new DecodeSignature(cacheRequest.getUri(), sampleSize, cacheRequest.getOptions().preferedConfig);
+ DecodeSignature decodeSignature = new DecodeSignature(cacheRequest.getUri(), sampleSize, cacheRequest.getOptions().preferredConfig);
Bitmap bitmap;
if ((bitmap = mMemoryCache.getBitmap(decodeSignature)) != null) {
imageCacherListener.onImageAvailable(new ImageResponse(bitmap, ImageReturnedFrom.DISK, ImageResponseStatus.SUCCESS));
} else {
decodeBitmapFromDisk(cacheRequest, decodeSignature, imageCacherListener);
}
- } else if (cacheRequest.isFileSystemRequest()) {
+ } else if (cacheRequest.isFileSystemRequest() || isCached) {
retrieveImageDetails(cacheRequest, imageCacherListener);
} else {
downloadImageFromNetwork(cacheRequest, imageCacherListener);
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageEntry.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageEntry.java
index 21ed1f0..0d9a494 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageEntry.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageEntry.java
@@ -8,12 +8,14 @@ class ImageEntry {
public long lastAccessedTime = creationTime;
public int sizeX = -1;
public int sizeY = -1;
+ public long fileSize;
+ public long expiry = Long.MAX_VALUE;
String getFileName() {
return Long.toString(id);
}
public boolean hasDetails() {
- return sizeX != -1 || sizeY != -1;
+ return sizeX != -1 || sizeY != -1 || fileSize != 0;
}
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageLoader.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageLoader.java
index dcdf277..0517c63 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageLoader.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageLoader.java
@@ -174,10 +174,6 @@ public void destroy() {
}
}
- public void notifyConfigurationChanged() {
- mDisplayUtility.notifyConfigurationChanged();
- }
-
/**
* The ImageLoader will default to the options provided here if no other options are provided.
*
@@ -614,7 +610,7 @@ public void precacheImageToDiskAndMemory(String uri, Dimensions bounds, Options
Options o = new Options();
o.autoDetectBounds = options.autoDetectBounds;
o.overrideSampleSize = options.overrideSampleSize;
- o.preferedConfig = options.preferedConfig;
+ o.preferredConfig = options.preferredConfig;
o.scalingPreference = options.scalingPreference;
o.useScreenSizeAsBounds = options.useScreenSizeAsBounds;
o.widthBounds = bounds.width;
@@ -921,6 +917,6 @@ public static enum ScalingPreference {
*
* Default value: null.
*/
- public Bitmap.Config preferedConfig = null;
+ public Bitmap.Config preferredConfig = null;
}
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageSystemDatabase.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageSystemDatabase.java
index 946d576..c14fbf8 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageSystemDatabase.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImageSystemDatabase.java
@@ -5,16 +5,13 @@
import android.content.Context;
import android.database.Cursor;
-import android.database.sqlite.SQLiteCursor;
-import android.database.sqlite.SQLiteCursorDriver;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteQuery;
import android.util.Log;
+import com.xtremelabs.imageutils.ImagesTable.Columns;
import com.xtremelabs.imageutils.db.Database;
import com.xtremelabs.imageutils.db.Table;
-class ImageSystemDatabase {
+class ImageSystemDatabase { // TODO should this be implementing an interface?
private final ImagesTable mImagesTable = ImagesTable.getInstance();
private final ImageSystemDatabaseObserver mObserver;
private Database mDatabase;
@@ -28,14 +25,7 @@ public void init(Context context) {
List> tables = new ArrayList>();
tables.add(mImagesTable);
- mDatabase = new Database(context, new SQLiteDatabase.CursorFactory() {
- @SuppressWarnings("deprecation")
- @Override
- public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query) {
- return new SQLiteCursor(db, masterQuery, editTable, query);
- }
- }, tables);
-
+ mDatabase = new Database(context, tables);
populateCache();
performBadFileCheck();
}
@@ -43,76 +33,84 @@ public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, Strin
public void beginWrite(String uri) {
ImageEntry entry = new ImageEntry();
entry.uri = uri;
- mImagesTable.insert(entry, mDatabase.getWritableDatabase());
+ entry.id = mImagesTable.insert(mDatabase.getWritableDatabase(), entry);
mCache.putEntry(entry);
}
public void endWrite(String uri) {
ImageEntry entry = mCache.getEntry(uri);
entry.onDisk = true;
+ mImagesTable.insert(mDatabase.getWritableDatabase(), entry);
+ }
+
+ public void bump(String uri) {
+ ImageEntry entry = mCache.getEntry(uri);
entry.lastAccessedTime = System.currentTimeMillis();
- mImagesTable.insert(entry, mDatabase.getWritableDatabase());
+ mImagesTable.insert(mDatabase.getWritableDatabase(), entry);
}
public void writeFailed(String uri) {
- ImageEntry entry = mCache.removeEntry(uri);
- String whereClause = ImagesTable.Columns.ID.getColumnName() + "=?";
- String[] whereArgs = new String[] { Long.toString(entry.id) };
- mImagesTable.delete(mDatabase.getWritableDatabase(), whereClause, whereArgs);
+ deleteEntry(uri);
+ }
+
+ public void deleteEntry(String uri) {
+ mCache.removeEntry(uri);
+ deleteRow(uri);
}
ImageEntry getEntry(String uri) {
return mCache.getEntry(uri);
}
+ long getTotalFileSize() {
+ String[] columns = new String[] { "SUM(" + Columns.FILE_SIZE.getName() + ")" };
+ Cursor cursor = mImagesTable.selectFromTable(mDatabase.getReadableDatabase(), columns, null, null, null, null, null, null);
+ cursor.moveToFirst();
+ long total = cursor.getLong(0);
+ cursor.close();
+ return total;
+ }
+
void clear() {
mCache.clear();
mImagesTable.onClear(mDatabase.getWritableDatabase());
}
- void submitDetails(String uri, Dimensions dimensions) {
+ void submitDetails(String uri, Dimensions dimensions, long fileSize) {
ImageEntry entry = mCache.getEntry(uri);
entry.sizeX = dimensions.width;
entry.sizeY = dimensions.height;
- mImagesTable.insert(entry, mDatabase.getWritableDatabase());
+ entry.fileSize = fileSize;
+ mImagesTable.insert(mDatabase.getWritableDatabase(), entry);
}
private void populateCache() {
Cursor allEntries = mImagesTable.selectAllFromTable(mDatabase.getReadableDatabase());
Log.d("JAMIE", "Entries in database: " + allEntries.getCount());
while (allEntries.moveToNext()) {
- ImageEntry entry = new ImageEntry();
- entry.id = allEntries.getLong(allEntries.getColumnIndex(ImagesTable.Columns.ID.getColumnName()));
- entry.uri = allEntries.getString(allEntries.getColumnIndex(ImagesTable.Columns.URI.getColumnName()));
- entry.creationTime = allEntries.getLong(allEntries.getColumnIndex(ImagesTable.Columns.CREATION_TIME.getColumnName()));
- entry.lastAccessedTime = allEntries.getLong(allEntries.getColumnIndex(ImagesTable.Columns.LAST_ACCESSED_TIME.getColumnName()));
- entry.onDisk = allEntries.getInt(allEntries.getColumnIndex(ImagesTable.Columns.ON_DISK.getColumnName())) == 1;
- entry.sizeX = allEntries.getInt(allEntries.getColumnIndex(ImagesTable.Columns.SIZE_X.getColumnName()));
- entry.sizeY = allEntries.getInt(allEntries.getColumnIndex(ImagesTable.Columns.SIZE_Y.getColumnName()));
-
+ ImageEntry entry = ImagesTable.getEntryFromCursor(allEntries);
mCache.putEntry(entry);
-
Log.d("JAMIE", "Recovered URI: " + entry.uri + ", ONDISK: " + entry.onDisk);
}
}
private void performBadFileCheck() {
- String onDiskColumn = ImagesTable.Columns.ON_DISK.getColumnName();
+ String onDiskColumn = ImagesTable.Columns.ON_DISK.getName();
Cursor cursor = mImagesTable.selectFromTable(mDatabase.getReadableDatabase(), onDiskColumn + "=?", new String[] { "0" });
while (cursor.moveToNext()) {
- Log.d("JAMIE", "Deleting an item. URI: " + cursor.getString(cursor.getColumnIndex(ImagesTable.Columns.URI.getColumnName())));
- int columnIndex = cursor.getColumnIndex(ImagesTable.Columns.ID.getColumnName());
- int badImageEntryId = cursor.getInt(columnIndex);
- String filename = Integer.toString(badImageEntryId);
-
- mObserver.onBadJournalEntry(filename);
- deleteRow(badImageEntryId);
+ ImageEntry entry = ImagesTable.getEntryFromCursor(cursor);
+ Log.d("JAMIE", "Deleting an item. URI: " + entry.uri);
+ deleteEntry(entry.uri);
+ mObserver.onBadJournalEntry(entry);
}
+ cursor.close();
}
- private void deleteRow(int badImageEntryId) {
- mImagesTable.delete(mDatabase.getWritableDatabase(), ImagesTable.Columns.ID.getColumnName() + "=?", new String[] { Integer.toString(badImageEntryId) });
+ private void deleteRow(String uri) {
+ String whereClause = ImagesTable.Columns.URI.getName() + "=?";
+ String[] whereArgs = new String[] { uri };
+ mImagesTable.delete(mDatabase.getWritableDatabase(), whereClause, whereArgs);
}
/**
@@ -123,8 +121,23 @@ void close() {
}
interface ImageSystemDatabaseObserver {
- void onBadJournalEntry(String filename);
+ void onBadJournalEntry(ImageEntry entry);
void onDetailsRequired(String filename);
}
+
+ public ImageEntry removeLRU() {
+ String orderBy = Columns.LAST_ACCESSED_TIME + " ASC";
+ String selection = Columns.ON_DISK.getName() + "=?";
+ Cursor cursor = mImagesTable.selectFromTable(mDatabase.getReadableDatabase(), null, selection, new String[] { "1" }, null, null, orderBy, Integer.toString(1));
+
+ ImageEntry entry = null;
+ if (cursor.moveToFirst()) {
+ entry = ImagesTable.getEntryFromCursor(cursor);
+ deleteEntry(entry.uri);
+ }
+
+ return entry;
+ }
+
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImagesTable.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImagesTable.java
index 4dbce47..172dec6 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImagesTable.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ImagesTable.java
@@ -3,104 +3,116 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
-import android.util.Log;
+import android.provider.BaseColumns;
import com.xtremelabs.imageutils.db.Table;
class ImagesTable extends Table {
- enum Columns {
- ID(0), URI(1), ON_DISK(2), CREATION_TIME(3), LAST_ACCESSED_TIME(4), SIZE_X(5), SIZE_Y(6);
-
- private final int mIndex;
+ private static final String TABLE_NAMES = "images";
- private Columns(int index) {
- mIndex = index;
- }
+ // must remain in same order as Columns enum
+ private static final String[] COLUMNS = {
+ BaseColumns._ID,
+ "uri",
+ "on_disk",
+ "creation_time",
+ "last_accessed_time",
+ "size_x",
+ "size_y",
+ "fileSize",
+ "expiry"};
- String getColumnName() {
- return mColumns[mIndex];
+ enum Columns {
+ ID,
+ URI,
+ ON_DISK,
+ CREATION_TIME,
+ LAST_ACCESSED_TIME,
+ SIZE_X,
+ SIZE_Y,
+ FILE_SIZE,
+ EXPIRY;
+
+ String getName() {
+ int index = ordinal();
+ return COLUMNS[index];
}
}
- private static class InstanceHolder {
- private static ImagesTable sInstance = new ImagesTable();
- }
-
- private final static String[] mColumns = { "_id", "uri", "on_disk", "creation_time", "last_accessed_time", "size_x", "size_y" };
- private final String mTableName = "images";
+ private static final ImagesTable sInstance = new ImagesTable();
static ImagesTable getInstance() {
- return InstanceHolder.sInstance;
+ return sInstance;
}
@Override
public String[] getColumns() {
- return mColumns;
+ return COLUMNS;
}
@Override
public String getTableName() {
- return mTableName;
- }
-
- @Override
- public void insert(ImageEntry item, SQLiteDatabase db) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(mColumns[1], item.uri);
- contentValues.put(mColumns[2], item.onDisk);
- contentValues.put(mColumns[3], item.creationTime);
- contentValues.put(mColumns[4], item.lastAccessedTime);
- contentValues.put(mColumns[5], item.sizeX);
- contentValues.put(mColumns[6], item.sizeY);
- Log.d("JAMIE", "Insertion result: " + db.insertWithOnConflict(mTableName, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE));
+ return TABLE_NAMES;
}
@Override
protected String getColumnsForCreation() {
- StringBuilder builder = new StringBuilder();
- builder.append(mColumns[0] + " INTEGER PRIMARY KEY AUTOINCREMENT, ");
- builder.append(mColumns[1] + " TEXT, ");
- builder.append(mColumns[2] + " INTEGER, ");
- builder.append(mColumns[3] + " BIGINT, ");
- builder.append(mColumns[4] + " BIGINT, ");
- builder.append(mColumns[5] + " INTEGER, ");
- builder.append(mColumns[6] + " INTEGER, ");
- return builder.toString();
+ String columns =
+ COLUMNS[0] + " INTEGER PRIMARY KEY, " +
+ COLUMNS[1] + " TEXT, " +
+ COLUMNS[2] + " INTEGER, " +
+ COLUMNS[3] + " INTEGER, " +
+ COLUMNS[4] + " INTEGER, " +
+ COLUMNS[5] + " INTEGER, " +
+ COLUMNS[6] + " INTEGER, " +
+ COLUMNS[7] + " INTEGER, " +
+ COLUMNS[8] + " INTEGER, ";
+ return columns;
}
@Override
protected String getUniqueString() {
- return mColumns[0] + ", " + mColumns[1];
+ return COLUMNS[1];
}
@Override
protected ContentValues toContentValues(ImageEntry item) {
ContentValues contentValues = new ContentValues();
- contentValues.put(mColumns[0], item.id);
- contentValues.put(mColumns[1], item.uri);
- contentValues.put(mColumns[2], item.onDisk);
- contentValues.put(mColumns[3], item.creationTime);
- contentValues.put(mColumns[4], item.lastAccessedTime);
- contentValues.put(mColumns[5], item.sizeX);
- contentValues.put(mColumns[6], item.sizeY);
+ // id is generated by DB, not model
+ contentValues.put(COLUMNS[1], item.uri);
+ contentValues.put(COLUMNS[2], item.onDisk ? 1 : 0);
+ contentValues.put(COLUMNS[3], item.creationTime);
+ contentValues.put(COLUMNS[4], item.lastAccessedTime);
+ contentValues.put(COLUMNS[5], item.sizeX);
+ contentValues.put(COLUMNS[6], item.sizeY);
+ contentValues.put(COLUMNS[7], item.fileSize);
+ contentValues.put(COLUMNS[8], item.expiry);
return contentValues;
}
- public ImageEntry getEntry(String uri, SQLiteDatabase db) {
+ public ImageEntry getEntry(SQLiteDatabase db, String uri) {
ImageEntry entry = null;
- Cursor cursor = selectFromTable(db, Columns.URI.getColumnName() + "=?", new String[] { uri });
- if (cursor.getCount() == 1) {
- entry = new ImageEntry();
- entry.id = cursor.getLong(cursor.getColumnIndex(Columns.ID.getColumnName()));
- entry.uri = cursor.getString(cursor.getColumnIndex(Columns.URI.getColumnName()));
- entry.creationTime = cursor.getLong(cursor.getColumnIndex(Columns.CREATION_TIME.getColumnName()));
- entry.lastAccessedTime = cursor.getLong(cursor.getColumnIndex(Columns.LAST_ACCESSED_TIME.getColumnName()));
- entry.onDisk = cursor.getInt(cursor.getColumnIndex(Columns.ON_DISK.getColumnName())) == 1;
- entry.sizeX = cursor.getInt(cursor.getColumnIndex(Columns.SIZE_X.getColumnName()));
- entry.sizeY = cursor.getInt(cursor.getColumnIndex(Columns.SIZE_Y.getColumnName()));
+ Cursor cursor = selectFromTable(db, Columns.URI.getName() + "=?", new String[] { uri });
+ if (cursor.moveToFirst()) {
+ entry = getEntryFromCursor(cursor);
}
return entry;
}
+
+ public static ImageEntry getEntryFromCursor(Cursor cursor) {
+ ImageEntry entry = new ImageEntry();
+ entry.id = cursor.getLong(0);
+ entry.uri = cursor.getString(1);
+ entry.onDisk = cursor.getInt(2) == 1;
+ entry.creationTime = cursor.getLong(3);
+ entry.lastAccessedTime = cursor.getLong(4);
+ entry.sizeX = cursor.getInt(5);
+ entry.sizeY = cursor.getInt(6);
+ entry.fileSize = cursor.getLong(7);
+ entry.expiry = cursor.getLong(8);
+ return entry;
+ }
+
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ViewDimensionsUtil.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ViewDimensionsUtil.java
index b4d56aa..53939e7 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/ViewDimensionsUtil.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/ViewDimensionsUtil.java
@@ -17,15 +17,15 @@
package com.xtremelabs.imageutils;
import android.graphics.Point;
-import android.view.ViewGroup;
+import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
class ViewDimensionsUtil {
public static Point getImageViewDimensions(ImageView imageView) {
Point dimensions = new Point();
- dimensions.x = getDimensions(imageView, true);
- dimensions.y = getDimensions(imageView, false);
+ dimensions.x = getDimension(imageView, true);
+ dimensions.y = getDimension(imageView, false);
if (dimensions.x <= 0) {
dimensions.x = -1;
}
@@ -35,41 +35,25 @@ public static Point getImageViewDimensions(ImageView imageView) {
return dimensions;
}
- private static int getDimensions(ImageView imageView, boolean isWidth) {
- LayoutParams params = imageView.getLayoutParams();
- if (params == null) {
- return -1;
- }
- int length = isWidth ? params.width : params.height;
- if (length == LayoutParams.WRAP_CONTENT) {
- return -1;
- } else if (length == LayoutParams.MATCH_PARENT) {
- try {
- return getParentDimensions((ViewGroup) imageView.getParent(), isWidth);
- } catch (ClassCastException e) {
- return -1;
- }
- } else {
- return length;
- }
- }
-
- private static int getParentDimensions(ViewGroup parent, boolean isWidth) {
+ private static int getDimension(View view, boolean isWidth) {
LayoutParams params;
- if (parent == null || (params = parent.getLayoutParams()) == null) {
- return -1;
- }
- int length = isWidth ? params.width : params.height;
- if (length == LayoutParams.WRAP_CONTENT) {
- return -1;
- } else if (length == LayoutParams.MATCH_PARENT) {
- try {
- return getParentDimensions((ViewGroup) parent.getParent(), isWidth);
- } catch (ClassCastException e) {
+ while (view != null && (params = view.getLayoutParams()) != null) {
+ int length = isWidth ? params.width : params.height;
+ if (length == LayoutParams.WRAP_CONTENT) {
return -1;
+
+ } else if (length == LayoutParams.MATCH_PARENT) {
+ try {
+ view = (View) view.getParent();
+ } catch (ClassCastException e) {
+ return -1;
+ }
+
+ } else {
+ return length;
}
- } else {
- return length;
}
+
+ return -1;
}
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Database.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Database.java
index 041db3e..2e18cf8 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Database.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Database.java
@@ -14,10 +14,14 @@ public class Database extends SQLiteOpenHelper {
private final List> mTables;
+ public Database(Context context, List> tables) {
+ this(context, null, tables);
+ }
+
public Database(Context context, CursorFactory factory, List> tables) {
super(context, DatabaseConfig.NAME, factory, DatabaseConfig.VERSION);
- if (tables == null)
- throw new IllegalArgumentException("The list of tables cannot be null!");
+ if (tables == null || tables.isEmpty())
+ throw new IllegalArgumentException("The list of tables cannot be null or empty!");
mTables = tables;
}
diff --git a/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Table.java b/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Table.java
index a8eac9f..256b62c 100644
--- a/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Table.java
+++ b/xl_image_utils_lib/src/com/xtremelabs/imageutils/db/Table.java
@@ -55,27 +55,40 @@ public Cursor selectAllFromTable(SQLiteDatabase db) {
return db.query(getTableName(), getColumns(), null, null, null, null, null);
}
+ public Cursor selectFromTable(SQLiteDatabase db, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
+ return db.query(getTableName(), columns, selection, selectionArgs, groupBy, having, orderBy, limit);
+ }
+
public Cursor selectFromTable(SQLiteDatabase db, String selection, String[] selectArgs) {
return db.query(getTableName(), getColumns(), selection, selectArgs, null, null, null);
}
- public void insert(List items, SQLiteDatabase db) {
+ public void insert(SQLiteDatabase db, List items) {
for (T item : items) {
- insert(item, db);
+ insert(db, item);
}
}
- public void insert(T item, SQLiteDatabase db) {
+ /**
+ * {@link SQLiteDatabase#insert(String, String, ContentValues)}
+ */
+ public long insert(SQLiteDatabase db, T item) {
ContentValues values = toContentValues(item);
- db.insertWithOnConflict(getTableName(), null, values, SQLiteDatabase.CONFLICT_REPLACE);
+ return db.insert(getTableName(), null, values);
}
- public void update(T item, String where, String[] whereArgs, SQLiteDatabase db) {
+ /**
+ * {@link SQLiteDatabase#update(String, ContentValues, String, String[])}
+ */
+ public int update(SQLiteDatabase db, T item, String where, String[] whereArgs) {
ContentValues values = toContentValues(item);
- db.updateWithOnConflict(getTableName(), values, where, whereArgs, SQLiteDatabase.CONFLICT_REPLACE);
+ return db.update(getTableName(), values, where, whereArgs);
}
- public void delete(SQLiteDatabase db, String whereClause, String[] whereArgs) {
- db.delete(getTableName(), whereClause, whereArgs);
+ /**
+ * {@link SQLiteDatabase#delete(String, String, String[])}
+ */
+ public int delete(SQLiteDatabase db, String whereClause, String[] whereArgs) {
+ return db.delete(getTableName(), whereClause, whereArgs);
}
}