ListView的用音乐专辑图片滞后 [英] ListView lags with Music Album pictures

查看:142
本文介绍了ListView的用音乐专辑图片滞后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立了应有的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 your Adapter

AlbumArtLoader mArtLoader;

Instantiate it using

mArtLoader = new AlbumArtLoader(context);

inside yourAdapter constructor, which receives Context from your Activity.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆