我想将Album-Artworks加载到我的音乐应用中,并在recyclerview中预览它们。我试过 Googles Developer Guide,但我实际上加载了大约200个位图,所以这不起作用!
我不知道如何做到这一点!
这是我目前的代码:
if (cSong != null && cSong.moveToFirst()) {
do {
int iIDCol = cSong.getColumnIndex(MediaStore.Audio.Media._ID);
int iTitleCol = cSong.getColumnIndex(MediaStore.Audio.Media.TITLE);
int iArtistCol = cSong.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int iAlbumCol = cSong.getColumnIndex(MediaStore.Audio.Media.ALBUM);
int iDurationCol = cSong.getColumnIndex(MediaStore.Audio.Media.DURATION);
int iAlbumIDCol = cSong.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID);
Bitmap bCover = null;
BitmapFactory.Options bOptions = new BitmapFactory.Options();
bOptions.inJustDecodeBounds = true;
//Throws OutOfMemoryError
/*try {
Uri ArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri uri = ContentUris.withAppendedId(ArtworkUri, iAlbumIDCol);
ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor(uri, "r");
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
BitmapFactory.decodeFileDescriptor(fd, null, bOptions);
bOptions.inSampleSize = calculateInSampleSize(bOptions, 100, 100);
bOptions.inJustDecodeBounds = false;
bCover = BitmapFactory.decodeFileDescriptor(fd, null, bOptions);
pfd = null;
fd = null;
}
}
catch (IOException ioe) {
BitmapFactory.decodeResource(mContext.getResources(), R.drawable.standardartwork, bOptions);
bOptions.inSampleSize = calculateInSampleSize(bOptions, 100, 100);
bOptions.inJustDecodeBounds = false;
bCover = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.standardartwork, bOptions);
}*/
SongList.add(new Song(cSong.getLong(iIDCol), cSong.getString(iTitleCol), cSong.getString(iArtistCol), cSong.getString(iAlbumCol), cSong.getInt(iDurationCol), bCover));
}
while (cSong.moveToNext());
我的任何InSampleSize方法:
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int size = 1;
if (height > reqHeight && width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / size) > reqHeight && (halfWidth / size) > reqWidth) {
size *= 2;
}
}
return size;
}
谢谢!
答案 0 :(得分:0)
在内存中保留200个位图并不是一个好主意,即使它们已缩减。最简单的解决方案是将Uri保存到封面而不是Bitmap,并仅在需要时解码Bitmap。
所以解析代码看起来像这样:
Uri artworkUri = Uri.parse("content://media/external/audio/albumart");
if (cSong != null && cSong.moveToFirst()) {
do {
int iIDCol = cSong.getColumnIndex(MediaStore.Audio.Media._ID);
int iTitleCol = cSong.getColumnIndex(MediaStore.Audio.Media.TITLE);
int iArtistCol = cSong.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int iAlbumCol = cSong.getColumnIndex(MediaStore.Audio.Media.ALBUM);
int iDurationCol = cSong.getColumnIndex(MediaStore.Audio.Media.DURATION);
int iAlbumIDCol = cSong.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID);
Uri coverUri = ContentUris.withAppendedId(artworkUri, iAlbumIDCol);
SongList.add(new Song(cSong.getLong(iIDCol), cSong.getString(iTitleCol), cSong.getString(iArtistCol), cSong.getString(iAlbumCol), cSong.getInt(iDurationCol), coverUri));
}
while (cSong.moveToNext());
在您的RecyclerView.Adapter
onBindViewHolder(RecyclerView.ViewHolder holder, int position)
方法中进行解码:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Bitmap image = decodeBitmap(songsList.get(position).getBitmapUrl());
if (image != null) {
holder.imageView.setImageBitmap(image);
} else {
holder.imageView.setImageResource(R.drawable.standardartwork);
}
}
private Bitmap decodeBitmap(Uri uri) {
ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor(uri, "r");
try {
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
BitmapFactory.decodeFileDescriptor(fd, null, bOptions);
bOptions.inSampleSize = calculateInSampleSize(bOptions, 100, 100);
bOptions.inJustDecodeBounds = false;
return BitmapFactory.decodeFileDescriptor(fd, null, bOptions);
} else {
return null;
}
} catch (IOException ioe) {
return null;
}
}
这样您就可以只在内存中保存您实际必须在屏幕上显示的位图,其他位置将被回收。
注意:这些片段仅用于说明如何解决您的问题,但这会降低RecyclerView的性能,因为解码是在主线程上完成的。如果您的图像相当小,您将不会注意到它,但如果它们很大,您将不得不异步解码。如果是大图像,请考虑使用库来进行图像处理,如Picasso或Glide。
答案 1 :(得分:0)
我通过使用Library Picasso来解决它,它处理图像的加载过程。
Picasso.with(mContext).load(ImageUri).resize(Width, Height).into(ImageView);