ImageLoaderpublic class ImageLoader extends Object
Fields Summary |
---|
private static final String | TAG | private ArrayList | mQueue | private ArrayList | mInProgress | private boolean | mDone | private ArrayList | mDecodeThreads | private android.os.Handler | mHandler | private int | mThreadCount |
Constructors Summary |
---|
public ImageLoader(android.os.Handler handler, int threadCount)
mThreadCount = threadCount;
mHandler = handler;
start();
|
Methods Summary |
---|
long | bitmapSize(android.graphics.Bitmap b)
return b.getWidth() * b.getHeight() * 4;
| public boolean | cancel(ImageManager.IImage image)
synchronized (mQueue) {
WorkItem w = new WorkItem(image, 0, null, false);
int existing = mQueue.indexOf(w);
if (existing >= 0) {
mQueue.remove(existing);
return true;
}
return false;
}
| synchronized void | clear(android.net.Uri uri)
| public synchronized void | dump()
synchronized (mQueue) {
if (Config.LOGV)
Log.v(TAG, "Loader queue length is " + mQueue.size());
}
| private void | dumpQueue(java.lang.String s)
synchronized (mQueue) {
StringBuilder sb = new StringBuilder(s);
for (int i = 0; i < mQueue.size(); i++) {
sb.append(mQueue.get(i).mTag + " ");
}
if (Config.LOGV)
Log.v(TAG, sb.toString());
}
| public android.graphics.Bitmap | getBitmap(ImageManager.IImage image, com.android.camera.ImageLoader$LoadedCallback imageLoadedRunnable, boolean postAtFront, boolean postBack)
return getBitmap(image, 0, imageLoadedRunnable, postAtFront, postBack);
| public android.graphics.Bitmap | getBitmap(ImageManager.IImage image, int tag, com.android.camera.ImageLoader$LoadedCallback imageLoadedRunnable, boolean postAtFront, boolean postBack)
synchronized (mDecodeThreads) {
if (mDecodeThreads.size() == 0) {
start();
}
}
long t1 = System.currentTimeMillis();
long t2,t3,t4;
synchronized (mQueue) {
t2 = System.currentTimeMillis();
WorkItem w = new WorkItem(image, tag, imageLoadedRunnable, postBack);
if (!mInProgress.contains(w)) {
boolean contains = mQueue.contains(w);
if (contains) {
if (postAtFront) {
// move this item to the front
mQueue.remove(w);
mQueue.add(0, w);
}
} else {
if (postAtFront)
mQueue.add(0, w);
else
mQueue.add(w);
mQueue.notifyAll();
}
}
if (false)
dumpQueue("+" + (postAtFront ? "F " : "B ") + tag + ": ");
t3 = System.currentTimeMillis();
}
t4 = System.currentTimeMillis();
// Log.v(TAG, "getBitmap breakdown: tot= " + (t4-t1) + "; " + "; " + (t4-t3) + "; " + (t3-t2) + "; " + (t2-t1));
return null;
| public void | pushToFront(ImageManager.IImage image)
synchronized (mQueue) {
WorkItem w = new WorkItem(image, 0, null, false);
int existing = mQueue.indexOf(w);
if (existing >= 1) {
WorkItem existingWorkItem = mQueue.remove(existing);
mQueue.add(0, existingWorkItem);
mQueue.notifyAll();
}
}
| private synchronized void | start()
if (Config.LOGV)
Log.v(TAG, "ImageLoader.start() <<<<<<<<<<<<<<<<<<<<<<<<<<<<");
synchronized (mDecodeThreads) {
if (mDecodeThreads.size() > 0)
return;
mDone = false;
for (int i = 0;i < mThreadCount; i++) {
Thread t = new Thread(new Runnable() {
// pick off items on the queue, one by one, and compute their bitmap.
// place the resulting bitmap in the cache. then post a notification
// back to the ui so things can get updated appropriately.
public void run() {
while (!mDone) {
WorkItem workItem = null;
synchronized (mQueue) {
if (mQueue.size() > 0) {
workItem = mQueue.remove(0);
mInProgress.add(workItem);
}
else {
try {
mQueue.wait();
} catch (InterruptedException ex) {
}
}
}
if (workItem != null) {
if (false)
dumpQueue("-" + workItem.mTag + ": ");
Bitmap b = null;
try {
b = workItem.mImage.miniThumbBitmap();
} catch (Exception ex) {
if (Config.LOGV) Log.v(TAG, "couldn't load miniThumbBitmap " + ex.toString());
// sd card removal or sd card full
}
if (b == null) {
if (Config.LOGV) Log.v(TAG, "unable to read thumbnail for " + workItem.mImage.fullSizeImageUri());
}
synchronized (mQueue) {
mInProgress.remove(workItem);
}
if (workItem.mOnLoadedRunnable != null) {
if (workItem.mPostBack) {
final WorkItem w1 = workItem;
final Bitmap bitmap = b;
if (!mDone) {
mHandler.post(new Runnable() {
public void run() {
w1.mOnLoadedRunnable.run(bitmap);
}
});
}
} else {
workItem.mOnLoadedRunnable.run(b);
}
}
}
}
}
});
t.setName("image-loader-" + i);
mDecodeThreads.add(t);
t.start();
}
}
| public void | stop()
if (Config.LOGV)
Log.v(TAG, "ImageLoader.stop " + mDecodeThreads.size() + " threads");
mDone = true;
synchronized (mQueue) {
mQueue.notifyAll();
}
while (mDecodeThreads.size() > 0) {
Thread t = mDecodeThreads.get(0);
try {
t.join();
mDecodeThreads.remove(0);
} catch (InterruptedException ex) {
// so now what?
}
}
| public static android.graphics.Bitmap | transform(android.graphics.Matrix scaler, android.graphics.Bitmap source, int targetWidth, int targetHeight, boolean scaleUp)
int deltaX = source.getWidth() - targetWidth;
int deltaY = source.getHeight() - targetHeight;
if (!scaleUp && (deltaX < 0 || deltaY < 0)) {
/*
* In this case the bitmap is smaller, at least in one dimension, than the
* target. Transform it by placing as much of the image as possible into
* the target and leaving the top/bottom or left/right (or both) black.
*/
Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b2);
int deltaXHalf = Math.max(0, deltaX/2);
int deltaYHalf = Math.max(0, deltaY/2);
Rect src = new Rect(
deltaXHalf,
deltaYHalf,
deltaXHalf + Math.min(targetWidth, source.getWidth()),
deltaYHalf + Math.min(targetHeight, source.getHeight()));
int dstX = (targetWidth - src.width()) / 2;
int dstY = (targetHeight - src.height()) / 2;
Rect dst = new Rect(
dstX,
dstY,
targetWidth - dstX,
targetHeight - dstY);
if (Config.LOGV)
Log.v(TAG, "draw " + src.toString() + " ==> " + dst.toString());
c.drawBitmap(source, src, dst, null);
return b2;
}
float bitmapWidthF = source.getWidth();
float bitmapHeightF = source.getHeight();
float bitmapAspect = bitmapWidthF / bitmapHeightF;
float viewAspect = (float) targetWidth / (float) targetHeight;
if (bitmapAspect > viewAspect) {
float scale = targetHeight / bitmapHeightF;
if (scale < .9F || scale > 1F) {
scaler.setScale(scale, scale);
} else {
scaler = null;
}
} else {
float scale = targetWidth / bitmapWidthF;
if (scale < .9F || scale > 1F) {
scaler.setScale(scale, scale);
} else {
scaler = null;
}
}
Bitmap b1;
if (scaler != null) {
// this is used for minithumb and crop, so we want to filter here.
b1 = Bitmap.createBitmap(source, 0, 0,
source.getWidth(), source.getHeight(), scaler, true);
} else {
b1 = source;
}
int dx1 = Math.max(0, b1.getWidth() - targetWidth);
int dy1 = Math.max(0, b1.getHeight() - targetHeight);
Bitmap b2 = Bitmap.createBitmap(
b1,
dx1/2,
dy1/2,
targetWidth,
targetHeight);
if (b1 != source)
b1.recycle();
return b2;
|
|