Cached bitmaps will now have the same size as their ImageViews

This commit is contained in:
daniel oeh 2012-08-26 21:53:34 +02:00
parent 40e0950c23
commit 616c247d84
9 changed files with 105 additions and 88 deletions

View File

@ -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" />
<TextView
android:id="@+id/txtvNewEps"

View File

@ -25,7 +25,7 @@ public class FeedInfoActivity extends SherlockActivity {
public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
private Feed feed;
private ImageView imgvCover;
private TextView txtvTitle;
private TextView txtvDescription;
@ -41,22 +41,32 @@ public class FeedInfoActivity extends SherlockActivity {
FeedManager manager = FeedManager.getInstance();
feed = manager.getFeed(feedId);
if (feed != null) {
if (AppConfig.DEBUG) Log.d(TAG, "Language is " + feed.getLanguage());
if (AppConfig.DEBUG) Log.d(TAG, "Author is " + feed.getAuthor());
if (AppConfig.DEBUG)
Log.d(TAG, "Language is " + feed.getLanguage());
if (AppConfig.DEBUG)
Log.d(TAG, "Author is " + feed.getAuthor());
imgvCover = (ImageView) findViewById(R.id.imgvCover);
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
txtvDescription = (TextView) findViewById(R.id.txtvDescription);
txtvLanguage = (TextView) findViewById(R.id.txtvLanguage);
txtvAuthor = (TextView) findViewById(R.id.txtvAuthor);
FeedImageLoader.getInstance().loadCoverBitmap(feed.getImage(), imgvCover);
imgvCover.post(new Runnable() {
@Override
public void run() {
FeedImageLoader.getInstance().loadThumbnailBitmap(
feed.getImage(), imgvCover);
}
});
txtvTitle.setText(feed.getTitle());
txtvDescription.setText(feed.getDescription());
if (feed.getAuthor() != null) {
txtvAuthor.setText(feed.getAuthor());
}
if (feed.getLanguage() != null) {
txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage()));
txtvLanguage.setText(LangUtils.getLanguageString(feed
.getLanguage()));
}
} else {
Log.e(TAG, "Activity was started with invalid arguments");
@ -64,27 +74,22 @@ public class FeedInfoActivity extends SherlockActivity {
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.feedinfo, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.support_item).setVisible(feed.getPaymentLink() != null);
menu.findItem(R.id.support_item).setVisible(
feed.getPaymentLink() != null);
menu.findItem(R.id.share_link_item).setVisible(feed.getLink() != null);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {

View File

@ -39,8 +39,8 @@ public class FeedlistAdapter extends ArrayAdapter<Feed> {
@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<Feed> {
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;
}

View File

@ -26,7 +26,7 @@ public class SearchlistAdapter extends ArrayAdapter<SearchResult> {
@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<SearchResult> {
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;

View File

@ -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);
}
}

View File

@ -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<String, Bitmap> coverCache;
private LruCache<String, Bitmap> 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;
}

View File

@ -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;
}

View File

@ -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());
}

View File

@ -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;
}
}