diff --git a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java new file mode 100644 index 000000000..3ed331a54 --- /dev/null +++ b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java @@ -0,0 +1,140 @@ +package de.danoeh.antennapod.asynctask; + +import java.io.File; + +import android.annotation.SuppressLint; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.AsyncTask; +import android.util.Log; +import android.widget.ImageView; +import de.danoeh.antennapod.AppConfig; +import de.danoeh.antennapod.PodcastApp; +import de.danoeh.antennapod.R; + +public abstract class BitmapDecodeWorkerTask extends + AsyncTask { + + private int PREFERRED_LENGTH; + + public static final int LENGTH_BASE_COVER = 200; + public static final int LENGTH_BASE_THUMBNAIL = 100; + + private static final String TAG = "BitmapDecodeWorkerTask"; + private ImageView target; + private Bitmap bitmap; + private Bitmap decodedBitmap; + + protected int baseLength; + + private String fileUrl; + + public BitmapDecodeWorkerTask(ImageView target, String fileUrl, int length) { + super(); + this.target = target; + this.fileUrl = fileUrl; + this.baseLength = length; + this.PREFERRED_LENGTH = (int) (length * PodcastApp.getLogicalDensity()); + } + + /** + * Should return true if tag of the imageview is still the same it was + * before the bitmap was decoded + */ + abstract protected boolean tagsMatching(ImageView target); + + @Override + protected void onPostExecute(Void result) { + super.onPostExecute(result); + // check if imageview is still supposed to display this image + if (tagsMatching(target)) { + target.setImageBitmap(bitmap); + } else { + if (AppConfig.DEBUG) + Log.d(TAG, "Not displaying image"); + } + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + private int calculateSampleSize(int width, int height) { + int max = Math.max(width, height); + if (max < PREFERRED_LENGTH) { + return 1; + } else { + // find first sample size where max / sampleSize < + // PREFERRED_LENGTH + for (int sampleSize = 1, power = 0;; power++, sampleSize = (int) Math + .pow(2, power)) { + int newLength = max / sampleSize; + if (newLength <= PREFERRED_LENGTH) { + if (newLength > 0) { + return sampleSize; + } else { + return sampleSize - 1; + } + } + } + } + } + + @Override + protected Void doInBackground(Void... params) { + File f = null; + if (fileUrl != null) { + f = new File(fileUrl); + } + if (fileUrl != null && f.exists()) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(fileUrl, options); + int sampleSize = calculateSampleSize(options.outWidth, + options.outHeight); + + options.inJustDecodeBounds = false; + options.inSampleSize = sampleSize; + decodedBitmap = BitmapFactory.decodeFile(fileUrl, + options); + if (decodedBitmap == null) { + Log.i(TAG, + "Bitmap could not be decoded in custom sample size. Trying default sample size (path was " + + fileUrl + ")"); + decodedBitmap = BitmapFactory.decodeFile(fileUrl); + } + if (decodedBitmap != null) { + bitmap = Bitmap.createScaledBitmap(decodedBitmap, + PREFERRED_LENGTH, PREFERRED_LENGTH, false); + storeBitmapInCache(bitmap); + } else { + Log.w(TAG, "Could not load bitmap. Using default image."); + bitmap = BitmapFactory.decodeResource(target.getResources(), + R.drawable.default_cover); + } + if (AppConfig.DEBUG) + Log.d(TAG, "Finished loading bitmaps"); + } else { + onInvalidFileUrl(); + } + return null; + } + + protected void onInvalidFileUrl() { + Log.e(TAG, "FeedImage has no valid file url. Using default image"); + bitmap = BitmapFactory.decodeResource(target.getResources(), + R.drawable.default_cover); + } + + protected abstract void storeBitmapInCache(Bitmap bitmap); + + @SuppressLint("NewApi") + public void executeAsync() { + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { + executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + execute(); + } + } +} diff --git a/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java b/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java index 7f28ed0bc..42ef186e3 100644 --- a/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java +++ b/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java @@ -1,22 +1,16 @@ package de.danoeh.antennapod.asynctask; -import java.io.File; - -import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.PodcastApp; -import de.danoeh.antennapod.feed.FeedImage; -import de.danoeh.antennapod.feed.FeedManager; -import de.danoeh.antennapod.storage.DownloadRequester; -import de.danoeh.antennapod.R; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.content.Context; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.AsyncTask; import android.support.v4.util.LruCache; -import android.util.Log; import android.widget.ImageView; +import de.danoeh.antennapod.PodcastApp; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.feed.FeedImage; +import de.danoeh.antennapod.feed.FeedManager; +import de.danoeh.antennapod.storage.DownloadRequester; /** Caches and loads FeedImage bitmaps in the background */ public class FeedImageLoader { @@ -78,7 +72,6 @@ public class FeedImageLoader { return singleton; } - @SuppressLint("NewApi") public void loadCoverBitmap(FeedImage image, ImageView target) { if (image != null) { Bitmap bitmap = getBitmapFromCoverCache(image.getId()); @@ -86,20 +79,15 @@ public class FeedImageLoader { target.setImageBitmap(bitmap); } else { target.setImageResource(R.drawable.default_cover); - BitmapWorkerTask worker = new BitmapWorkerTask(target, image, - LENGTH_BASE_COVER); - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - worker.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } else { - worker.execute(); - } + FeedImageDecodeWorkerTask worker = new FeedImageDecodeWorkerTask( + target, image, LENGTH_BASE_COVER); + worker.executeAsync(); } } else { target.setImageResource(R.drawable.default_cover); } } - @SuppressLint("NewApi") public void loadThumbnailBitmap(FeedImage image, ImageView target) { if (image != null) { Bitmap bitmap = getBitmapFromThumbnailCache(image.getId()); @@ -107,13 +95,9 @@ public class FeedImageLoader { target.setImageBitmap(bitmap); } else { target.setImageResource(R.drawable.default_cover); - BitmapWorkerTask worker = new BitmapWorkerTask(target, image, - LENGTH_BASE_THUMBNAIL); - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - worker.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } else { - worker.execute(); - } + FeedImageDecodeWorkerTask worker = new FeedImageDecodeWorkerTask( + target, image, LENGTH_BASE_THUMBNAIL); + worker.executeAsync(); } } else { target.setImageResource(R.drawable.default_cover); @@ -149,119 +133,44 @@ public class FeedImageLoader { coverCache.put(id, bitmap); } - class BitmapWorkerTask extends AsyncTask { + class FeedImageDecodeWorkerTask extends BitmapDecodeWorkerTask { - private int PREFERRED_LENGTH; + private static final String TAG = "FeedImageDecodeWorkerTask"; - private static final String TAG = "BitmapWorkerTask"; - private ImageView target; - private Bitmap bitmap; - private Bitmap decodedBitmap; - - private int baseLength; + protected FeedImage image; - private FeedImage image; - - public BitmapWorkerTask(ImageView target, FeedImage image, int length) { - super(); - this.target = target; + public FeedImageDecodeWorkerTask(ImageView target, FeedImage image, + int length) { + super(target, image.getFile_url(), length); this.image = image; - this.baseLength = length; - this.PREFERRED_LENGTH = (int) (length * PodcastApp - .getLogicalDensity()); } @Override - protected void onPostExecute(Void result) { - super.onPostExecute(result); - // check if imageview is still supposed to display this image - if (target.getTag() == null || target.getTag() == image) { - target.setImageBitmap(bitmap); - } else { - if (AppConfig.DEBUG) - Log.d(TAG, "Not displaying image"); + protected boolean tagsMatching(ImageView target) { + return target.getTag() == null || target.getTag() == image; + } + + @Override + protected void storeBitmapInCache(Bitmap bitmap) { + if (baseLength == LENGTH_BASE_COVER) { + addBitmapToCoverCache(image.getId(), bitmap); + } else if (baseLength == LENGTH_BASE_THUMBNAIL) { + addBitmapToThumbnailCache(image.getId(), bitmap); } } @Override - protected void onPreExecute() { - super.onPreExecute(); + protected void onInvalidFileUrl() { + super.onInvalidFileUrl(); + if (image.getFile_url() != null + && !DownloadRequester.getInstance() + .isDownloadingFile(image)) { + FeedManager.getInstance().notifyInvalidImageFile( + PodcastApp.getInstance(), image); + } + } - private int calculateSampleSize(int width, int height) { - int max = Math.max(width, height); - if (max < PREFERRED_LENGTH) { - return 1; - } else { - // find first sample size where max / sampleSize < - // PREFERRED_LENGTH - for (int sampleSize = 1, power = 0;; power++, sampleSize = (int) Math - .pow(2, power)) { - int newLength = max / sampleSize; - if (newLength <= PREFERRED_LENGTH) { - if (newLength > 0) { - return sampleSize; - } else { - return sampleSize - 1; - } - } - } - } - } - - @Override - protected Void doInBackground(Void... params) { - File f = null; - if (image.getFile_url() != null) { - f = new File(image.getFile_url()); - } - if (image.getFile_url() != null && f.exists()) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(image.getFile_url(), options); - int sampleSize = calculateSampleSize(options.outWidth, - options.outHeight); - - options.inJustDecodeBounds = false; - options.inSampleSize = sampleSize; - decodedBitmap = BitmapFactory.decodeFile(image.getFile_url(), - options); - if (decodedBitmap == null) { - Log.i(TAG, - "Bitmap could not be decoded in custom sample size. Trying default sample size (path was " - + image.getFile_url() + ")"); - decodedBitmap = BitmapFactory.decodeFile(image - .getFile_url()); - } - if (decodedBitmap != null) { - bitmap = Bitmap.createScaledBitmap(decodedBitmap, - PREFERRED_LENGTH, PREFERRED_LENGTH, false); - if (baseLength == LENGTH_BASE_COVER) { - addBitmapToCoverCache(image.getId(), bitmap); - } else if (baseLength == LENGTH_BASE_THUMBNAIL) { - addBitmapToThumbnailCache(image.getId(), bitmap); - } - } else { - Log.w(TAG, "Could not load bitmap. Using default image."); - bitmap = BitmapFactory.decodeResource( - target.getResources(), R.drawable.default_cover); - } - if (AppConfig.DEBUG) - Log.d(TAG, "Finished loading bitmaps"); - } else { - Log.e(TAG, - "FeedImage has no valid file url. Using default image"); - bitmap = BitmapFactory.decodeResource(target.getResources(), - R.drawable.default_cover); - if (image.getFile_url() != null - && !DownloadRequester.getInstance().isDownloadingFile( - image)) { - FeedManager.getInstance().notifyInvalidImageFile( - PodcastApp.getInstance(), image); - } - } - return null; - } } }