diff --git a/res/layout/feedlist_item.xml b/res/layout/feedlist_item.xml index 070d214c1..6457ca872 100644 --- a/res/layout/feedlist_item.xml +++ b/res/layout/feedlist_item.xml @@ -14,7 +14,10 @@ android:layout_centerVertical="true" android:layout_marginLeft="1dip" android:layout_marginRight="4dip" - android:cropToPadding="true" /> + android:adjustViewBounds="true" + android:cropToPadding="true" + android:scaleType="fitXY" + android:src="@drawable/default_cover" /> { @Override public View getView(int position, View convertView, ViewGroup parent) { - Holder holder; - Feed feed = getItem(position); + final Holder holder; + final Feed feed = getItem(position); // Inflate Layout if (convertView == null) { @@ -94,12 +94,14 @@ public class FeedlistAdapter extends ArrayAdapter { holder.newEpisodes.setVisibility(View.INVISIBLE); } holder.image.setTag(feed.getImage()); - /*if (PodcastApp.getInstance().isLargeScreen()) { - imageLoader.loadCoverBitmap(feed.getImage(), holder.image); - } else {*/ - imageLoader.loadThumbnailBitmap(feed.getImage(), holder.image); - //} + holder.image.post(new Runnable() { + + @Override + public void run() { + imageLoader.loadThumbnailBitmap(feed.getImage(), holder.image); + } + }); return convertView; } diff --git a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java index 126790f39..f12a852f8 100644 --- a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java +++ b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java @@ -26,7 +26,7 @@ public class SearchlistAdapter extends ArrayAdapter { @Override public View getView(int position, View convertView, ViewGroup parent) { - Holder holder; + final Holder holder; SearchResult result = getItem(position); FeedComponent component = result.getComponent(); @@ -48,21 +48,34 @@ public class SearchlistAdapter extends ArrayAdapter { holder = (Holder) convertView.getTag(); } if (component.getClass() == Feed.class) { - Feed feed = (Feed) component; + final Feed feed = (Feed) component; holder.title.setText(feed.getTitle()); holder.subtitle.setVisibility(View.GONE); - FeedImageLoader.getInstance().loadThumbnailBitmap(feed.getImage(), - holder.cover); + holder.cover.post(new Runnable() { + + @Override + public void run() { + FeedImageLoader.getInstance().loadThumbnailBitmap( + feed.getImage(), holder.cover); + } + }); } else if (component.getClass() == FeedItem.class) { - FeedItem item = (FeedItem) component; + final FeedItem item = (FeedItem) component; holder.title.setText(item.getTitle()); if (result.getSubtitle() != null) { holder.subtitle.setVisibility(View.VISIBLE); holder.subtitle.setText(result.getSubtitle()); } - FeedImageLoader.getInstance().loadThumbnailBitmap(item.getFeed().getImage(), - holder.cover); + holder.cover.post(new Runnable() { + + @Override + public void run() { + FeedImageLoader.getInstance().loadThumbnailBitmap( + item.getFeed().getImage(), holder.cover); + } + }); + } return convertView; diff --git a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java index c18763d48..66341dfde 100644 --- a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java +++ b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java @@ -17,32 +17,27 @@ import de.danoeh.antennapod.util.BitmapDecoder; public abstract class BitmapDecodeWorkerTask extends Thread { protected int PREFERRED_LENGTH; - - public static final int LENGTH_BASE_COVER = 200; - public static final int LENGTH_BASE_THUMBNAIL = 100; + + /** Can be thumbnail or cover */ + protected int imageType; private static final String TAG = "BitmapDecodeWorkerTask"; private ImageView target; protected Bitmap bitmap; private Bitmap decodedBitmap; - protected int baseLength; - protected String fileUrl; private Handler handler; public BitmapDecodeWorkerTask(Handler handler, ImageView target, - String fileUrl, int length) { + String fileUrl, int length, int imageType) { super(); this.handler = handler; this.target = target; this.fileUrl = fileUrl; - this.baseLength = length; - this.PREFERRED_LENGTH = (int) (length * PodcastApp.getLogicalDensity() + 0.5f); - if (PodcastApp.getInstance().isLargeScreen()) { - this.PREFERRED_LENGTH *= 2.0; - } + this.PREFERRED_LENGTH = length; + this.imageType = imageType; } /** @@ -108,9 +103,9 @@ public abstract class BitmapDecodeWorkerTask extends Thread { protected void storeBitmapInCache(Bitmap bitmap) { FeedImageLoader loader = FeedImageLoader.getInstance(); - if (baseLength == LENGTH_BASE_COVER) { + if (imageType == FeedImageLoader.IMAGE_TYPE_COVER) { loader.addBitmapToCoverCache(fileUrl, bitmap); - } else if (baseLength == LENGTH_BASE_THUMBNAIL) { + } else if (imageType == FeedImageLoader.IMAGE_TYPE_THUMBNAIL) { loader.addBitmapToThumbnailCache(fileUrl, bitmap); } } diff --git a/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java b/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java index 06173087b..66128fb4e 100644 --- a/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java +++ b/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java @@ -25,8 +25,8 @@ public class FeedImageLoader { private static final String TAG = "FeedImageLoader"; private static FeedImageLoader singleton; - public static final int LENGTH_BASE_COVER = 300; - public static final int LENGTH_BASE_THUMBNAIL = 100; + public static final int IMAGE_TYPE_THUMBNAIL = 0; + public static final int IMAGE_TYPE_COVER = 1; private static final String CACHE_DIR = "miroguide_thumbnails"; private static final int CACHE_SIZE = 20 * 1024 * 1024; @@ -45,7 +45,7 @@ public class FeedImageLoader { // Use 1/8th of the available memory for this memory cache. final int coverCacheSize = 1024 * 1024 * memClass / 8; - final int thumbnailCacheSize = 1024 * 1024 * memClass / 6; + final int thumbnailCacheSize = 1024 * 1024 * memClass / 8; private LruCache coverCache; private LruCache thumbnailCache; @@ -103,6 +103,12 @@ public class FeedImageLoader { return singleton; } + /** + * Load a bitmap from the cover cache. If the bitmap is not in the cache, it + * will be loaded from the disk. This method should either be called if the + * ImageView's size has already been set or inside a Runnable which is posted + * to the ImageView's message queue. + */ public void loadCoverBitmap(FeedImage image, ImageView target) { if (image != null && image.getFile_url() != null) { Bitmap bitmap = getBitmapFromCoverCache(image.getFile_url()); @@ -111,7 +117,8 @@ public class FeedImageLoader { } else { target.setImageResource(R.drawable.default_cover); FeedImageDecodeWorkerTask worker = new FeedImageDecodeWorkerTask( - handler, target, image, LENGTH_BASE_COVER); + handler, target, image, target.getHeight(), + IMAGE_TYPE_COVER); executor.submit(worker); } } else { @@ -119,6 +126,12 @@ public class FeedImageLoader { } } + /** + * Load a bitmap from the thumbnail cache. If the bitmap is not in the cache, it + * will be loaded from the disk. This method should either be called if the + * ImageView's size has already been set or inside a Runnable which is posted + * to the ImageView's message queue. + */ public void loadThumbnailBitmap(FeedImage image, ImageView target) { if (image != null && image.getFile_url() != null) { Bitmap bitmap = getBitmapFromThumbnailCache(image.getFile_url()); @@ -127,7 +140,8 @@ public class FeedImageLoader { } else { target.setImageResource(R.drawable.default_cover); FeedImageDecodeWorkerTask worker = new FeedImageDecodeWorkerTask( - handler, target, image, LENGTH_BASE_THUMBNAIL); + handler, target, image, target.getHeight(), + IMAGE_TYPE_THUMBNAIL); executor.submit(worker); } } else { @@ -135,7 +149,8 @@ public class FeedImageLoader { } } - public void loadMiroGuideThumbnail(MiroGuideChannel channel, ImageView target) { + public void loadMiroGuideThumbnail(MiroGuideChannel channel, + ImageView target) { if (channel.getThumbnailUrl() != null) { Bitmap bitmap = getBitmapFromThumbnailCache(channel .getThumbnailUrl()); @@ -145,7 +160,7 @@ public class FeedImageLoader { target.setImageResource(R.drawable.default_cover); executor.submit(new MiroGuideThumbnailDownloader(handler, - target, channel, LENGTH_BASE_THUMBNAIL)); + target, channel, target.getHeight(), coverCacheSize)); } else { target.setImageBitmap(bitmap); } @@ -198,8 +213,8 @@ public class FeedImageLoader { protected FeedImage image; public FeedImageDecodeWorkerTask(Handler handler, ImageView target, - FeedImage image, int length) { - super(handler, target, image.getFile_url(), length); + FeedImage image, int length, int imageType) { + super(handler, target, image.getFile_url(), length, imageType); this.image = image; } diff --git a/src/de/danoeh/antennapod/asynctask/MiroGuideThumbnailDownloader.java b/src/de/danoeh/antennapod/asynctask/MiroGuideThumbnailDownloader.java index 121fe5f49..566d444e2 100644 --- a/src/de/danoeh/antennapod/asynctask/MiroGuideThumbnailDownloader.java +++ b/src/de/danoeh/antennapod/asynctask/MiroGuideThumbnailDownloader.java @@ -25,8 +25,8 @@ public class MiroGuideThumbnailDownloader extends BitmapDecodeWorkerTask { private MiroGuideChannel miroChannel; public MiroGuideThumbnailDownloader(Handler handler, ImageView target, - MiroGuideChannel miroChannel, int length) { - super(handler, target, miroChannel.getThumbnailUrl(), length); + MiroGuideChannel miroChannel, int length, int imageType) { + super(handler, target, miroChannel.getThumbnailUrl(), length, imageType); this.miroChannel = miroChannel; } diff --git a/src/de/danoeh/antennapod/fragment/CoverFragment.java b/src/de/danoeh/antennapod/fragment/CoverFragment.java index 08e09cea5..062924696 100644 --- a/src/de/danoeh/antennapod/fragment/CoverFragment.java +++ b/src/de/danoeh/antennapod/fragment/CoverFragment.java @@ -83,8 +83,15 @@ public class CoverFragment extends SherlockFragment { } private void loadMediaInfo() { - FeedImageLoader.getInstance().loadCoverBitmap( - media.getItem().getFeed().getImage(), imgvCover); + imgvCover.post(new Runnable() { + + @Override + public void run() { + FeedImageLoader.getInstance().loadCoverBitmap( + media.getItem().getFeed().getImage(), imgvCover); + } + }); + txtvTitle.setText(media.getItem().getTitle()); txtvFeed.setText(media.getItem().getFeed().getTitle()); } diff --git a/src/de/danoeh/antennapod/util/BitmapDecoder.java b/src/de/danoeh/antennapod/util/BitmapDecoder.java index 84cff582f..3d966ee96 100644 --- a/src/de/danoeh/antennapod/util/BitmapDecoder.java +++ b/src/de/danoeh/antennapod/util/BitmapDecoder.java @@ -7,26 +7,12 @@ import android.util.Log; public class BitmapDecoder { private static final String TAG = "BitmapDecoder"; - private static int calculateSampleSize(int preferredLength, int width, - int height) { - int max = Math.max(width, height); - if (max < preferredLength) { - 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 <= preferredLength) { - if (newLength > 0) { - return sampleSize; - } else { - return sampleSize - 1; - } - } - } + private static int calculateSampleSize(int preferredLength, int length) { + int sampleSize = 1; + if (length > preferredLength) { + sampleSize = Math.round(((float) length / (float) preferredLength)); } + return sampleSize; } public static Bitmap decodeBitmap(int preferredLength, String fileUrl) { @@ -35,14 +21,13 @@ public class BitmapDecoder { BitmapFactory.decodeFile(fileUrl, options); int srcWidth = options.outWidth; int srcHeight = options.outHeight; - int sampleSize = calculateSampleSize(preferredLength, srcWidth, - srcHeight); - + int length = Math.max(srcWidth, srcHeight); + int sampleSize = calculateSampleSize(preferredLength, length); + Log.d(TAG, "Using samplesize " + sampleSize); options.inJustDecodeBounds = false; options.inSampleSize = sampleSize; options.inPreferredConfig = Bitmap.Config.ARGB_8888; - options.inScaled = true; - + Bitmap decodedBitmap = BitmapFactory.decodeFile(fileUrl, options); if (decodedBitmap == null) { Log.i(TAG, @@ -50,14 +35,6 @@ public class BitmapDecoder { + fileUrl + ")"); decodedBitmap = BitmapFactory.decodeFile(fileUrl); } - if (decodedBitmap != null) { - return decodedBitmap; - /* - return Bitmap.createScaledBitmap(decodedBitmap, - preferredLength, preferredLength, false); - */ - } else { - return null; - } + return decodedBitmap; } }