ListView的用音乐专辑图片滞后 [英] ListView lags with Music Album pictures
问题描述
我建立了应有的albumcover的标题ARTISTNAME和图像一个ListView音乐播放器。这似乎变得非常laggy。如何提高性能?
我的函数来获得这些图片是这样的:
公共静态位图getAlbumart(上下文的背景下,龙album_id){
位图BM = NULL;
BitmapFactory.Options选项=新BitmapFactory.Options();
尝试{
最后乌里sArtworkUri = Uri.parse(内容://媒体/外部/音频/ albumart);
URI URI = ContentUris.withAppendedId(sArtworkUri,album_id);
ParcelFileDescriptor PFD = context.getContentResolver()openFileDescriptor(URI,R)。
如果(PFD!= NULL){
FD的FileDescriptor = pfd.getFileDescriptor();
BM = BitmapFactory.de codeFileDescriptor(FD,空,期权);
PFD = NULL;
FD = NULL;
}
}赶上(错误EE){BM = BitmapFactory.de codeResource(context.getResources(),R.drawable.cd_128x128); }
赶上(例外五){BM = BitmapFactory.de codeResource(context.getResources(),R.drawable.cd_128x128);}
返回BM;}
如果我在getView功能做到这一点,每次在App杀死自己。于是,我就先救他们位图的ArrayList的但是这个时间太长。我已经尝试过了Viewholder但这真的不影响性能。
我getview看起来像这样
`@覆盖
公共查看getView(INT位置,查看视图的ViewGroup父){ 查看rview =视图。
支架=无效;
如果(rview == NULL)
{
LayoutInflater吹气= context.getLayoutInflater();
rview = inflater.inflate(R.layout.row_song,空,真);
持有人=新ViewHolder(rview);
rview.setTag(保持器);
}
其他
{
支架=(ViewHolder)rview.getTag();
}
holder.imgAlbumart.setImageBitmap(Music.getAlbumart(上下文,Long.valueOf(AL_songlist.get(位置).getAlbumID()))); holder.txtTitle.setText(AL_songlist.get(位置).getTitle());
holder.txtArtist.setText(AL_songlist.get(位置).getArtist());
返回rview;
}`
这是相同的,当我尝试过。
android.provider.MediaStore.Audio.AlbumColumns.ALBUM_ART
块引用>解决方案使用我的
AlbumArtLoader.java
。我是从Android开发者网站,但无法找到该网页。我修改它,使之比所提供的code顺畅。/ *加载图像在平稳的ListView * /
公共类AlbumArtLoader {
私人上下文CTX;
私人诠释artSize;
私人最终位图mPlaceHolderBitmap;
私人绘制对象[] =可绘制新绘制对象[2];
公共AlbumArtLoader(上下文C){
CTX = C;
artSize = c.getResources()getDimensionPixelSize(R.dimen.albumart_size)。
mPlaceHolderBitmap = BitmapFactory.de codeResource(ctx.getResources(),R.drawable.transparent);
mPlaceHolderBitmap = Bitmap.createScaledBitmap(mPlaceHolderBitmap,artSize,artSize,FALSE);
可绘制[0] =新BitmapDrawable(ctx.getResources(),mPlaceHolderBitmap);
}
类BitmapWorkerTask扩展的AsyncTask<弦乐,太虚,TransitionDrawable> {
私人最终的WeakReference< ImageView的> imageViewReference;
私人字符串路径;
公共BitmapWorkerTask(ImageView的ImageView的){
//使用的WeakReference,确保ImageView的可以被垃圾收集
imageViewReference =新的WeakReference< ImageView的>(ImageView的);
}
//在后台德code图像。
@覆盖
保护TransitionDrawable doInBackground(字符串... PARAMS){
路径=参数[0];
// TransitionDrawable让你做2绘项目之间的交叉淡入淡出动画
//它增加光滑的感觉
TransitionDrawable TD = NULL; //该albumart_unknown位图重新对每个相册没有专辑封面,以保持甚至滚动
如果(路径== NULL){
位图B = Bitmap.createScaledBitmap(BitmapFactory.de codeResource(ctx.getResources(),R.drawable.albumart_unknown),artSize,artSize,真正的);
可绘[1] =新BitmapDrawable(ctx.getResources(),B);
}其他{
位图B:
尝试{
B = Bitmap.createScaledBitmap(BitmapFactory.de codeFILE(路径),artSize,artSize,真正的);
}赶上(例外五){
B = Bitmap.createScaledBitmap(BitmapFactory.de codeResource(ctx.getResources(),R.drawable.albumart_unknown),artSize,artSize,真正的);
}
可绘[1] =新BitmapDrawable(ctx.getResources(),B);
}
TD =新TransitionDrawable(可绘制);
td.setCrossFadeEnabled(真);
返回运输署;
}
//完成后,看是否ImageView的仍然是围绕并设置位图。
@覆盖
保护无效onPostExecute(TransitionDrawable TD){
如果(isCancelled()){
TD = NULL;
}
如果(imageViewReference = NULL&放大器;!&安培;!TD = NULL){
最后ImageView的ImageView的= imageViewReference.get();
最后BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(ImageView的);
如果(这== bitmapWorkerTask和放大器;&安培;!ImageView的= NULL){
imageView.setImageDrawable(TD);
td.startTransition(200);
}
}
}
} 公共无效loadBitmap(字符串路径,ImageView的ImageView的){
如果(cancelPotentialWork(路径,ImageView的)){
最后BitmapWorkerTask任务=新BitmapWorkerTask(ImageView的);
最后AsyncDrawable asyncDrawable =新AsyncDrawable(ctx.getResources(),mPlaceHolderBitmap,任务);
imageView.setImageDrawable(asyncDrawable);
task.execute(路径);
}
} 静态类AsyncDrawable扩展BitmapDrawable {
私人最终的WeakReference< BitmapWorkerTask> bitmapWorkerTaskReference;
公共AsyncDrawable(资源资源,位图的位图,BitmapWorkerTask bitmapWorkerTask){
超(RES,位图);
bitmapWorkerTaskReference =新的WeakReference< BitmapWorkerTask>(bitmapWorkerTask);
}
公共BitmapWorkerTask getBitmapWorkerTask(){
返回bitmapWorkerTaskReference.get();
}
} 公共静态布尔cancelPotentialWork(字符串路径,ImageView的ImageView的){
最后BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(ImageView的);
如果(bitmapWorkerTask!= NULL){
最后弦乐的位图数据= bitmapWorkerTask.path;
//如果位图数据尚未设置,或者它从新的数据不同
如果(位图数据== NULL ||位图数据!=路径){
//取消previous任务
bitmapWorkerTask.cancel(真);
}其他{
//同样的工作已在进行中
返回false;
}
}
//没有任务与ImageView的关联,或者现有任务被取消
返回true;
} // Helper方法
私有静态BitmapWorkerTask getBitmapWorkerTask(ImageView的ImageView的){
如果(ImageView的!= NULL){
最终可绘制可绘制= imageView.getDrawable();
如果(绘制的instanceof AsyncDrawable){
最后AsyncDrawable asyncDrawable =(AsyncDrawable)绘制;
返回asyncDrawable.getBitmapWorkerTask();
}
}
返回null;
}
}要使用它,创建在
适配器一个
AlbumArtLoader
实例AlbumArtLoader mArtLoader;
使用实例化它
mArtLoader =新AlbumArtLoader(背景);
您
适配器
的构造函数,它接收在上下文
从活动
。然后在
getView()
mArtLoader.loadBitmap(pathToAlbumArt,vh.imgAlbumart);
EXTRA:从你的光标获取专辑封面路径
INT artColumnIndex = albumCursor.getColumnIndex(MediaStore.Audio.AlbumColumns.ALBUM_ART);如果(albumCursor =空&放大器;!&放大器; albumCursor.moveToFirst()){
做{
字符串artPath = albumCursor.getString(artColumnIndex);
}而(albumCursor.moveToNext());
}I'm building a music player which should have a listView with title-artistname and Image of the albumcover. This seems to get very laggy. How can I improve performance?
My function to get these pictures is like this:
public static Bitmap getAlbumart(Context context,Long album_id){ Bitmap bm = null; BitmapFactory.Options options = new BitmapFactory.Options(); try{ final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart"); Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id); ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r"); if (pfd != null){ FileDescriptor fd = pfd.getFileDescriptor(); bm = BitmapFactory.decodeFileDescriptor(fd, null, options); pfd = null; fd = null; } } catch(Error ee){bm = BitmapFactory.decodeResource(context.getResources(),R.drawable.cd_128x128); } catch (Exception e) { bm = BitmapFactory.decodeResource(context.getResources(),R.drawable.cd_128x128);} return bm;}
If I do this everytime in my getView function the App kills itself. So I tried to save them first in a Arraylist of Bitmaps but this takes too long. I already tried with a Viewholder but this really doesn't affect the performance.
My getview looks like this
`@Override public View getView(int position, View view, ViewGroup parent) { View rview = view; holder = null; if (rview == null) { LayoutInflater inflater = context.getLayoutInflater(); rview= inflater.inflate(R.layout.row_song, null, true); holder = new ViewHolder(rview); rview.setTag(holder); } else { holder = (ViewHolder) rview.getTag(); } holder.imgAlbumart.setImageBitmap(Music.getAlbumart(context, Long.valueOf(AL_songlist.get(position).getAlbumID()))); holder.txtTitle.setText(AL_songlist.get(position).getTitle()); holder.txtArtist.setText(AL_songlist.get(position).getArtist()); return rview; }`
EDIT:
It's the same when I try it through.
android.provider.MediaStore.Audio.AlbumColumns.ALBUM_ART
解决方案Use my
AlbumArtLoader.java
. I got it from android developers website but can't find the page. I modified it to make it smoother than the provided code./* Loads images smoothly in ListView */ public class AlbumArtLoader { private Context ctx; private int artSize; private final Bitmap mPlaceHolderBitmap; private Drawable[] drawables = new Drawable[2]; public AlbumArtLoader(Context c) { ctx = c; artSize = c.getResources().getDimensionPixelSize(R.dimen.albumart_size); mPlaceHolderBitmap = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.transparent); mPlaceHolderBitmap = Bitmap.createScaledBitmap(mPlaceHolderBitmap, artSize, artSize, false); drawables[0] = new BitmapDrawable(ctx.getResources(), mPlaceHolderBitmap); } class BitmapWorkerTask extends AsyncTask<String, Void, TransitionDrawable> { private final WeakReference<ImageView> imageViewReference; private String path; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can be garbage collected imageViewReference = new WeakReference<ImageView>(imageView); } // Decode image in background. @Override protected TransitionDrawable doInBackground(String... params) { path = params[0]; // TransitionDrawable let you to make a crossfade animation between 2 drawables // It increase the sensation of smoothness TransitionDrawable td = null; // The albumart_unknown bitmap is recreated for each album without album art to maintain even scrolling if(path == null) { Bitmap b = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(ctx.getResources(), R.drawable.albumart_unknown), artSize, artSize, true); drawables[1] = new BitmapDrawable(ctx.getResources(), b); } else { Bitmap b; try { b = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(path), artSize, artSize, true); } catch(Exception e) { b = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(ctx.getResources(), R.drawable.albumart_unknown), artSize, artSize, true); } drawables[1] = new BitmapDrawable(ctx.getResources(), b); } td = new TransitionDrawable(drawables); td.setCrossFadeEnabled(true); return td; } // Once complete, see if ImageView is still around and set bitmap. @Override protected void onPostExecute(TransitionDrawable td) { if(isCancelled()) { td = null; } if(imageViewReference != null && td != null) { final ImageView imageView = imageViewReference.get(); final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if(this == bitmapWorkerTask && imageView != null) { imageView.setImageDrawable(td); td.startTransition(200); } } } } public void loadBitmap(String path, ImageView imageView) { if(cancelPotentialWork(path, imageView)) { final BitmapWorkerTask task = new BitmapWorkerTask(imageView); final AsyncDrawable asyncDrawable = new AsyncDrawable(ctx.getResources(), mPlaceHolderBitmap, task); imageView.setImageDrawable(asyncDrawable); task.execute(path); } } static class AsyncDrawable extends BitmapDrawable { private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { super(res, bitmap); bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>(bitmapWorkerTask); } public BitmapWorkerTask getBitmapWorkerTask() { return bitmapWorkerTaskReference.get(); } } public static boolean cancelPotentialWork(String path, ImageView imageView) { final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if(bitmapWorkerTask != null) { final String bitmapData = bitmapWorkerTask.path; // If bitmapData is not yet set or it differs from the new data if(bitmapData == null || bitmapData != path) { // Cancel previous task bitmapWorkerTask.cancel(true); } else { // The same work is already in progress return false; } } // No task associated with the ImageView, or an existing task was cancelled return true; } // Helper method private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { if(imageView != null) { final Drawable drawable = imageView.getDrawable(); if(drawable instanceof AsyncDrawable) { final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; return asyncDrawable.getBitmapWorkerTask(); } } return null; } }
To use it, create an
AlbumArtLoader
instance in yourAdapter
AlbumArtLoader mArtLoader;
Instantiate it using
mArtLoader = new AlbumArtLoader(context);
inside your
Adapter
constructor, which receivesContext
from yourActivity
.Then in
getView()
mArtLoader.loadBitmap(pathToAlbumArt, vh.imgAlbumart);
EXTRA: To get album art path from your cursor
int artColumnIndex = albumCursor.getColumnIndex(MediaStore.Audio.AlbumColumns.ALBUM_ART); if(albumCursor!=null && albumCursor.moveToFirst()) { do { String artPath = albumCursor.getString(artColumnIndex); } while (albumCursor.moveToNext()); }
这篇关于ListView的用音乐专辑图片滞后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!