版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010356768/article/details/83026260
最后可以对图片进行压缩,可以查看
https://blog.csdn.net/u010356768/article/details/83016046
增加BitmapUtils文件后
MusicAdapter中修改以下方法
private Bitmap loadBitmap(String url){
try {
InputStream is = HttpUtils.getInputStream(url);
//执行压缩算法,获取合适尺寸的图片
Bitmap bitmap = BitmapUtils.loadBitmap(is,5,5);
//Bitmap bitmap = BitmapFactory.decodeStream(is);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
如何使用软引用实现内存缓存
修改MusicAdapter
/**
* 音乐列表适配器
*/
public class MusicAdapter extends BaseAdapter {
......
private ListView listView;
private HashMap<String,SoftReference<Bitmap>> cache = new HashMap<>();
......
/**
* 通过url地址 发送http请求 获取图片
* @param url
* @return
*/
private Bitmap loadBitmap(String url){
try {
InputStream is = HttpUtils.getInputStream(url);
//执行压缩算法,获取合适尺寸的图片
Bitmap bitmap = BitmapUtils.loadBitmap(is,50,50);
//Bitmap bitmap = BitmapFactory.decodeStream(is);
//把bitmap放入内存缓存
cache.put(url,new SoftReference<Bitmap>(bitmap));
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
......
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
......
//给holder.imgPic设置图片
//先去内存缓存中看有没有
SoftReference<Bitmap> ref = cache.get(music.getPic_small());
if(ref!=null){//以前存过
Bitmap bitmap = ref.get();
if(bitmap!=null){//以前存的还没有被清掉
holder.imgPic.setImageBitmap(bitmap);
return view;
}
}
//向任务集合中一个图片下载任务
holder.imgPic.setTag(music.getPic_small());
......
return view;
}
......
}
文件缓存
BitmapUtils增加如下方法
/**
* 用jpeg格式存储bitmap
*
* @param bitmap
* @param file
*/
public static void save(Bitmap bitmap, File file) throws IOException {
if (!file.getParentFile().exists()) {//父目录不存在
file.getParentFile().mkdirs();
}
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
}
/**
* 从文件中加载一个Bitmap
*
* @param file
* @return
*/
public static Bitmap bitmap(File file) {
if (!file.exists()) {
return null;
}
Bitmap b = BitmapFactory.decodeFile(file.getAbsolutePath());
return b;
}
MusicAdapter修改如下
/**
* 音乐列表适配器
*/
public class MusicAdapter extends BaseAdapter {
......
private ListView listView;
private HashMap<String,SoftReference<Bitmap>> cache = new HashMap<>();
......
/**
* 通过url地址 发送http请求 获取图片
* @param url
* @return
*/
private Bitmap loadBitmap(String url){
try {
InputStream is = HttpUtils.getInputStream(url);
//执行压缩算法,获取合适尺寸的图片
Bitmap bitmap = BitmapUtils.loadBitmap(is,50,50);
//Bitmap bitmap = BitmapFactory.decodeStream(is);
//把bitmap放入内存缓存
cache.put(url,new SoftReference<Bitmap>(bitmap));
//把bitmap存入文件中
//data/data/包名/cache文件夹 内部存储的缓存目录
String fileName = url.substring(url.lastIndexOf("/")+1);
Log.d("IMAGES",fileName);
File file = new File(context.getCacheDir(),"images/"+fileName);
BitmapUtils.save(bitmap,file);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
......
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
......
//图片在服务器,本来该起线程显示的,但是,这是adapter.getView()方法
//每次图片显示时,都要启线程的话,手机会炸的...
//给holder.imgPic设置图片
//先去内存缓存中看有没有
SoftReference<Bitmap> ref = cache.get(music.getPic_small());
if(ref!=null){//以前存过
Bitmap bitmap = ref.get();
if(bitmap!=null){//以前存的还没有被清掉
holder.imgPic.setImageBitmap(bitmap);
return view;
}
}
//去文件缓存中读取
String url = music.getPic_small();
String fileName = url.substring(url.lastIndexOf("/")+1);
File file = new File(context.getCacheDir(),"images/"+fileName);
Bitmap bitmap = BitmapUtils.bitmap(file);
if(bitmap!=null){
//一旦从文件中读取出来,先存入内存缓存
//内存是最快的
cache.put(url,new SoftReference<Bitmap>(bitmap));
holder.imgPic.setImageBitmap(bitmap);
return view;
}
//向任务集合中一个图片下载任务
......
return view;
}
......
}
查看data/data/包名/cache可以看到下载的图片
封装
新增ImageLoader
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ListView;
import com.example.xx.v4.R;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* 异步批量加载图片的工具类
*/
public class ImageLoader {
private HashMap<String,SoftReference<Bitmap>> cache = new HashMap<>();
private Context context;
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 ImageLoader(Context context,ListView listView) {
this.context = context;
this.listView = listView;
//启动工作线程,轮循任务集合
//匿名内部类持有外部类对象引用
//在匿名内部类中可以使用MusicAdapter.this
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();
}
public void stopThread(){
//isLoop为false,循环停止
isLoop = false;
//当我们按返回键时,线程在wait(),应先唤醒
synchronized (workThread) {
workThread.notify();
}
}
public void displayImage(String url, ImageView imageView){
//先去内存缓存中看有没有
SoftReference<Bitmap> ref = cache.get(url);
if(ref!=null){//以前存过
Bitmap bitmap = ref.get();
if(bitmap!=null){//以前存的还没有被清掉
imageView.setImageBitmap(bitmap);
return;
}
}
//去文件缓存中读取
String fileName = url.substring(url.lastIndexOf("/")+1);
File file = new File(context.getCacheDir(),"images/"+fileName);
Bitmap bitmap = BitmapUtils.bitmap(file);
if(bitmap!=null){
//一旦从文件中读取出来,先存入内存缓存
//内存是最快的
cache.put(url,new SoftReference<Bitmap>(bitmap));
imageView.setImageBitmap(bitmap);
return;
}
//向任务集合中一个图片下载任务
imageView.setTag(url);
ImageLoaderTask task = new ImageLoaderTask();
task.path = url;
tasks.add(task);
//唤醒工作线程,起来干活
synchronized (workThread) {
workThread.notify();
}
}
class ImageLoaderTask{
String path;//保存图片下载路径
Bitmap bitmap;//下载成功后的图片
}
/**
* 通过url地址 发送http请求 获取图片
* @param url
* @return
*/
private Bitmap loadBitmap(String url){
try {
InputStream is = HttpUtils.getInputStream(url);
//执行压缩算法,获取合适尺寸的图片
Bitmap bitmap = BitmapUtils.loadBitmap(is,50,50);
//Bitmap bitmap = BitmapFactory.decodeStream(is);
//把bitmap放入内存缓存
cache.put(url,new SoftReference<Bitmap>(bitmap));
//把bitmap存入文件中
//data/data/包名/cache文件夹 内部存储的缓存目录
String fileName = url.substring(url.lastIndexOf("/")+1);
Log.d("IMAGES",fileName);
File file = new File(context.getCacheDir(),"images/"+fileName);
BitmapUtils.save(bitmap,file);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
MusicAdapter修改为
import android.content.Context;
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.ImageLoader;
import java.util.List;
/**
* 音乐列表适配器
*/
public class MusicAdapter extends BaseAdapter {
private Context context;
private List<Music> musics;
private LayoutInflater inflater;
private ImageLoader imageLoader;
public MusicAdapter(Context context, List<Music> musics, ListView listView) {
super();
this.context = context;
this.musics = musics;
this.inflater = LayoutInflater.from(context);
this.imageLoader = new ImageLoader(context,listView);
}
@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设置图片
imageLoader.displayImage(music.getPic_small(),holder.imgPic);
return view;
}
public void stopThread() {
imageLoader.stopThread();
}
class ViewHolder{
ImageView imgPic;
TextView tvName;
TextView tvSinger;
}
}