版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010356768/article/details/83012590
ListView中异步批量加载图片业务
使用单线程轮循任务队列的机制完成该业务
效果图
MusicAdapter
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
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.ListView;
import android.widget.TextView;
import com.example.xx.v4.R;
import com.example.xx.v4.entity.Music;
import com.example.xx.v4.util.HttpUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 音乐列表适配器
*/
public class MusicAdapter extends BaseAdapter {
private Context context;
private List<Music> musics;
private LayoutInflater inflater;
private List<ImageLoaderTask> tasks = new ArrayList<ImageLoaderTask>();
private Thread workThread;
private boolean isLoop = true;
private ListView listView;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case HANDLER_IMAGE_LOAD_SUCCESS:
//给相应的Imageview设置bitmap
ImageLoaderTask task = (ImageLoaderTask)msg.obj;
Bitmap bitmap = task.bitmap;
ImageView imageView = (ImageView) listView.findViewWithTag(task.path);
if(imageView != null){
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
}else {
imageView.setImageResource(R.mipmap.ic_launcher);
}
}
break;
}
}
};
public static final int HANDLER_IMAGE_LOAD_SUCCESS = 1;
public MusicAdapter(Context context, List<Music> musics, ListView listView) {
this.context = context;
this.musics = musics;
this.inflater = LayoutInflater.from(context);
this.listView = listView;
//启动工作线程,轮循任务集合
workThread = new Thread(){
@Override
public void run() {
while (isLoop){
if(!tasks.isEmpty()){//不是空集合
ImageLoaderTask task = tasks.remove(0);//remove的同时返回该数据
String url = task.path;
//发送http请求 下载图片
Bitmap bitmap = loadBitmap(url);
task.bitmap = bitmap;
//更新界面 发消息给Handler
Message message = new Message();
message.what = HANDLER_IMAGE_LOAD_SUCCESS;
message.obj = task;
handler.sendMessage(message);
}else {//空集合 等待
try {
//锁
synchronized (workThread) {
workThread.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
workThread.start();
}
/**
* 通过url地址 发送http请求 获取图片
* @param url
* @return
*/
private Bitmap loadBitmap(String url){
try {
InputStream is = HttpUtils.getInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(is);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public int getCount() {
return musics.size();
}
@Override
public Music getItem(int i) {
return musics.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
if(view == null){
view = inflater.inflate(R.layout.item_lv_music,null);
holder = new ViewHolder();
holder.imgPic = view.findViewById(R.id.img_Pic);
holder.tvName = view.findViewById(R.id.tv_name);
holder.tvSinger = view.findViewById(R.id.tv_singer);
view.setTag(holder);
}
holder = (ViewHolder) view.getTag();
//给控件赋值
Music music = getItem(i);
holder.tvName.setText(music.getTitle());
holder.tvSinger.setText(music.getAuthor());
//图片在服务器,本来该起线程显示的,但是,这是adapter.getView()方法
//每次图片显示时,都要启线程的话,手机会炸的...
//给holder.imgPic设置图片
//向任务集合中一个图片下载任务
holder.imgPic.setTag(music.getPic_small());
ImageLoaderTask task = new ImageLoaderTask();
task.path = music.getPic_small();
tasks.add(task);
//唤醒工作线程,起来干活
synchronized (workThread) {
workThread.notify();
}
return view;
}
class ViewHolder{
ImageView imgPic;
TextView tvName;
TextView tvSinger;
}
class ImageLoaderTask{
String path;//保存图片下载路径
Bitmap bitmap;//下载成功后的图片
}
}
NewMusicListFrament修改如下
......
/**
* 更新Adapter
* @param musics
*/
public void setAdapter(List<Music> musics){
adapter = new MusicAdapter(getActivity(),musics,listView);
listView.setAdapter(adapter);
}
重点都写在注释里了