专辑图片展示
ListView中异步批量加载图片业务
使用单线程轮循任务队列的机制完成该业务
修改接口多传一个参数 type,查询综合信息,修改 UrlFactory
public class UrlFactory {
/**
* url地址
*
* @param keyword
* @return json
*/
public static String getNewMusicListUrl(String keyword) {
String url = "https://v2.alapi.cn/api/music/search?token=注册网站用户中心查看token&keyword=" + keyword+"&type=1018";
return url;
}
}
查看返回 json 数据
由于返回结构改变了,所以相应实体类
public class MusicDataModel {
public MusicSongModel song;
}
public class MusicSongModel {
public List<MusicItem> songs;
}
public class MusicItem {
public String id;
public String name;
public String albumName;
public String albumPic;
public AlbumModel al;
}
public class AlbumModel {
public String name;
public String picUrl;
}
修改 JsonParser
public class JsonParser {
/**
* 通过输入流,通过XMLPULL解析方式 解析xml内容
*
* @param is
* @return List<Music>
*/
public static List<MusicItem> parseMusicList(InputStream is) throws IOException, JSONException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
String json = sb.toString();
JSONObject obj = new JSONObject(json);
JSONObject data = obj.getJSONObject("data");
JSONObject song = data.getJSONObject("song");
JSONArray songs = song.getJSONArray("songs");
List<MusicItem> list = new ArrayList<>();
for (int i = 0; i < songs.length(); i++) {
JSONObject s = songs.getJSONObject(i);
String id = s.getString("id");
String name = s.getString("name");
MusicItem musicItem = new MusicItem();
musicItem.id = id;
musicItem.name = name;
musicItem.albumName = s.getJSONObject("al").getString("name");
musicItem.albumPic = s.getJSONObject("al").getString("picUrl");
list.add(musicItem);
}
return list;
}
}
修改 MusicAdapter
public class MusicAdapter extends BaseAdapter {
private Context context;
private List<MusicItem> 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<MusicItem> musics, ListView listView) {
super(context, musics);
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 MusicItem 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.tvAlbum = view.findViewById(R.id.tv_album);
view.setTag(holder);
}
holder = (ViewHolder) view.getTag();
//给控件赋值
MusicItem music = getItem(i);
holder.tvName.setText(music.name);
holder.tvAlbum.setText(music.albumName);
//图片在服务器,本来该起线程显示的,但是,这是adapter.getView()方法
//每次图片显示时,都要启线程的话,手机会炸的...
//给holder.imgPic设置图片
//向任务集合中一个图片下载任务
holder.imgPic.setTag(music.albumPic);
ImageLoaderTask task = new ImageLoaderTask();
task.path = music.albumPic;
tasks.add(task);
//唤醒工作线程,起来干活
synchronized (workThread) {
workThread.notify();
}
return view;
}
class ViewHolder {
ImageView imgPic;
TextView tvName;
TextView tvAlbum;
}
class ImageLoaderTask {
String path;//保存图片下载路径
Bitmap bitmap;//下载成功后的图片
}
}
NewMusicListFrament 修改如下
public void setAdapter(List<MusicItem> musics) {
adapter = new MusicAdapter(getActivity(), musics, listView);
listView.setAdapter(adapter);
}
运行程序
图片压缩
Bitmap 图片压缩(位图对象)
常见图片格式:
JPG:最常用的压缩格式,压缩比率高,但是不支持透明色
PNG:支持透明色
GIF:支持动态图
提供一个工具类用来压缩 bitmap
BitmapUtils
public class BitmapUtils {
/**
* 压缩图片,获取相应尺寸的图片
*
* @param is 输入流
* @param width 目标宽度
* @param height 目标高度
* @return
*/
public static Bitmap loadBitmap(InputStream is, int width, int height) throws IOException {
//把is解析,把数据读取到byte[]中
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//把输入流中的数据读取到bos中
byte[] buffer = new byte[1024 * 8];
int length = 0;
while ((length = is.read(buffer)) != -1) {
bos.write(buffer, 0, length);
bos.flush();
}
//该byte数组描述的是一个图片的完整信息
byte[] bytes = bos.toByteArray();
//获取图片原始尺寸
BitmapFactory.Options options = new BitmapFactory.Options();
//仅仅加载边界属性
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
//根据原始尺寸和width、height计算压缩比例
int w = options.outWidth / width;
int h = options.outHeight / height;
int scale = w > h ? w : h;
//执行压缩
options.inJustDecodeBounds = false;
options.inSampleSize = scale;//设置缩放比例
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
return bitmap;
}
}
使用
Bitmap bitmap = BitmapUtils.loadBitmap(is,5,5);
应用到刚才的项目,修改 MusicAdapter 的 loadBitmap 方法
private Bitmap loadBitmap(String url) {
try {
InputStream is = HttpUtils.getInputStream(url);
Bitmap bitmap = BitmapUtils.loadBitmap(is,100,100);
//Bitmap bitmap = BitmapFactory.decodeStream(is);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}