您的位置:首页 > 其它

【安卓】使用多线程实现ListView中图片的异步加载

2016-08-24 17:36 453 查看
ListView中图片的加载问题十分突出,因为程序读取图片资源十分耗时,而如果把设置图片放到主线程中的话,在下滑时会感觉到明显的卡顿,用户体验非常之差。

于是我想到设置图片这一步肯定不能不再主线程中进行。必须使用异步加载图片来实现。

PS:程序中所有耗时的工作绝对不能再主线程进行,必须异步。

以下是部分核心代码:

package jiaoml.com.music.adapter;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
 
import java.util.ArrayList;
 
import jiaoml.com.music.R;
import jiaoml.com.music.music.Mp3Info;
import jiaoml.com.music.utils.MediaUtils;
 
/**
* Created by 91905 on 2016/8/17 0017.
*/
 
public class FragmentMusicAdapter extends BaseAdapter {
    private Context context;
    private ArrayList<Mp3Info> mp3Infos;
    private static final int LOAD_IMAGE = 1;
 
    public FragmentMusicAdapter(Context context) {
        this.context = context;
        mp3Infos = MediaUtils.getMp3Infos(context);
    }
 
    @Override
    public int getCount() {
        return mp3Infos.size();
    }
 
    @Override
    public Object getItem(int i) {
        return mp3Infos.get(i);
    }
 
    @Override
    public long getItemId(int i) {
        return i;
    }
 
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder vh;
        if (view == null) {
            view = LayoutInflater.from(context).inflate(R.layout.fragment_music_music_item, null);
            vh = new ViewHolder();
            vh.ablum = (ImageView) view.findViewById(R.id.music_ablum);
            vh.title = (TextView) view.findViewById(R.id.music_title);
            vh.artist = (TextView) view.findViewById(R.id.music_artist);
            view.setTag(vh);
        } else {
            vh = (ViewHolder) view.getTag();
        }
        Mp3Info mp3Info = mp3Infos.get(i);
        vh.ablum.setImageResource(R.mipmap.music_default);
        new ImageLoader().showImageByThread(vh.ablum, mp3Info);
        vh.title.setText(mp3Info.getTitle());
        vh.artist.setText(mp3Info.getArtist());
        return view;
    }
 
    class ViewHolder {
        ImageView ablum;
        TextView title;
        TextView artist;
    }
 
    /**
     * 异步加载图片
     */
    class ImageLoader {
        private ImageView imageView;
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                  imageView.setImageBitmap((Bitmap) msg.obj);
            }
        };
 
 
        /**
         * 使用多线程实现异步加载
         * @param imageView
         * @param mp3Info
         */
        public void showImageByThread(ImageView imageView, final Mp3Info mp3Info) {
            this.imageView = imageView;
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    Message message = Message.obtain();
                    Bitmap bitmap = getBitmap(mp3Info);
                    message.obj = bitmap;
                    handler.sendMessage(message);
                }
            }.start();
        }
 
        public Bitmap getBitmap(Mp3Info mp3Info) {
            return MediaUtils.getArtwork(context, mp3Info.getId(), mp3Info.getAlbumId(), true, true);
        }
    }
}


这样虽然完成了异步加载,但同时出现了一个十分严重的问题,我将getBitmap方法改为如下形式,以模拟加载延迟:

package jiaoml.com.music.adapter;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
 
import java.util.ArrayList;
 
import jiaoml.com.music.R;
import jiaoml.com.music.music.Mp3Info;
import jiaoml.com.music.utils.MediaUtils;
 
/**
* Created by 91905 on 2016/8/17 0017.
*/
 
public class FragmentMusicAdapter extends BaseAdapter {
    private Context context;
    private ArrayList<Mp3Info> mp3Infos;
    private static final int LOAD_IMAGE = 1;
 
    public FragmentMusicAdapter(Context context) {
        this.context = context;
        mp3Infos = MediaUtils.getMp3Infos(context);
    }
 
    @Override
    public int getCount() {
        return mp3Infos.size();
    }
 
    @Override
    public Object getItem(int i) {
        return mp3Infos.get(i);
    }
 
    @Override
    public long getItemId(int i) {
        return i;
    }
 
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder vh;
        if (view == null) {
            view = LayoutInflater.from(context).inflate(R.layout.fragment_music_music_item, null);
            vh = new ViewHolder();
            vh.ablum = (ImageView) view.findViewById(R.id.music_ablum);
            vh.title = (TextView) view.findViewById(R.id.music_title);
            vh.artist = (TextView) view.findViewById(R.id.music_artist);
            view.setTag(vh);
        } else {
            vh = (ViewHolder) view.getTag();
        }
        Mp3Info mp3Info = mp3Infos.get(i);
        vh.ablum.setImageResource(R.mipmap.music_default);
        vh.ablum.setTag(mp3Info);
        new ImageLoader().showImageByThread(vh.ablum, mp3Info);
        vh.title.setText(mp3Info.getTitle());
        vh.artist.setText(mp3Info.getArtist());
        return view;
    }
 
    class ViewHolder {
        ImageView ablum;
        TextView title;
        TextView artist;
    }
 
    /**
     * 异步加载图片
     */
    class ImageLoader {
        private ImageView imageView;
        private Mp3Info mp3Info;
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (imageView.getTag() == mp3Info) {
                    imageView.setImageBitmap((Bitmap) msg.obj);
                }
            }
        };
 
 
        /**
         * 使用多线程实现异步加载
         * @param imageView
         * @param mp3Info
         */
        public void showImageByThread(ImageView imageView, final Mp3Info mp3Info) {
            this.imageView = imageView;
            this.mp3Info = mp3Info;
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    Message message = Message.obtain();
                    Bitmap bitmap = getBitmap(mp3Info);
                    message.obj = bitmap;
                    handler.sendMessage(message);
                }
            }.start();
        }
 
        public Bitmap getBitmap(Mp3Info mp3Info) {
            return MediaUtils.getArtwork(context, mp3Info.getId(), mp3Info.getAlbumId(), true, true);
        }
    }
}


以上我通过给ImageView设置Tag为mp3Info,并传递给加载图片的函数,当设置图片时判断mp3Info和ImageView标记的是否相同,相同则设置,不相同则不设置.

这样一来就完美的解决了ListView加载图片卡顿的问题,同时也解决了图片异步加载错乱的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息