Android-单线程轮循机制批量下载图片、图片压缩、内存泄漏、图片缓存、文件缓存

ListView异步批量加载图片

单线程轮循机制批量下载图片

例如:imageloader框架底层也是这么实现的!

思路:主线程向任务集合添加一个任务,工作线程从任务集合移除第一个任务,如果有任务一直移除,一直轮循,拿到图片之后解析成Bitmap,呈现的imageView当中。

这里写图片描述

package com.tarena.musicclient.adapter;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.activity.R;
import com.tarena.musicclient.entity.Music;
import com.tarena.musicclient.util.BitmapUtils;
import com.tarena.musicclient.util.GlobalConsts;
import com.tarena.musicclient.util.HttpUtils;

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;

public class MusicAdapter extends BaseAdapter{
    private Context context;
    private List<Music> musics;
    private LayoutInflater inflater;
    //(2)声明任务集合  
    private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
    private ListView listView;
    //声明用于轮循任务集合的工作线程
    private Thread workThread;
    //声明变量控制while循环
    private boolean isLoop=true;
    //声明缓存集合
    private HashMap<String, SoftReference<Bitmap>> cache 
        =new HashMap<String, SoftReference<Bitmap>>();

    //声明Handler  更新ImageView
    private Handler handler=new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case HANDLER_LOAD_IMAGE_SUCCESS:
                //给ImageView设置Bitmap
                ImageLoadTask task=(ImageLoadTask)msg.obj;
                //通过tag寻找到相应的ImageView
                ImageView ivAlum=(ImageView)listView.findViewWithTag(task.position);
                if(ivAlum!=null){
                    if(task.bitmap!=null){
                        ivAlum.setImageBitmap(task.bitmap);
                    }else{
                        ivAlum.setImageResource(R.drawable.ic_launcher);
                    }
                }
                break;
            }
        }
    };

    public static final int HANDLER_LOAD_IMAGE_SUCCESS=0;


    public MusicAdapter(Context context, List<Music> musics, ListView listView) {
        this.context=context;
        this.musics=musics;
        this.listView=listView;
        inflater=LayoutInflater.from(context);
        //(5)MusicAdapter有几个,工作线程就有几个
        //对workThread进行初始化
        workThread=new Thread(){
            public void run() {
                //(6)不断轮循任务集合
                while(isLoop){
                    //如果任务集合不是空集  
                    if(!tasks.isEmpty()){
                        //获取任务对象并且发送请求 
                        ImageLoadTask task = tasks.remove(0);
                        //通过路径返回Bitmap对象
                        Bitmap bitmap=loadBitmap(task.path);
                        task.bitmap=bitmap;
                        //给相应的ImageView设置Bitmap   handler
                        Message msg=new Message();
                        msg.what=HANDLER_LOAD_IMAGE_SUCCESS;
                        msg.obj=task;
                        handler.sendMessage(msg);
                    }else{
                        //同步代码块:一但调用了某个对象的wait()/notify()方法后,外面一定套一个以这个对象为锁的同步代码块
                        synchronized (workThread) {
                            //如果任务集合是空集  wait等待
                            try {
                                workThread.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        };
        workThread.start();
    }

    /**
     * 通过path  获取Bitmap
     * @param path
     * @return
     */
    public Bitmap loadBitmap(String path){
        Bitmap bitmap=null;
        String uri=GlobalConsts.BASEURL+path;
        try {
            //实体转成字节数组,字节数组转成图片
            HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, uri, null);
            byte[] bytes=EntityUtils.toByteArray(entity);
            bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
            //向缓存集合中存储缓存图片
            cache.put(path, new SoftReference<Bitmap>(bitmap));

        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    public int getCount() {
        return musics.size();
    }

    public Object getItem(int position) {
        return musics.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder=null;
        if(convertView==null){
            convertView=inflater.inflate(R.layout.item_lv_music, null);
            holder=new ViewHolder();
            holder.ivAlbum=(ImageView)convertView.findViewById(R.id.imageView1);
            holder.tvName=(TextView)convertView.findViewById(R.id.tvName);
            holder.tvDuration=(TextView)convertView.findViewById(R.id.tvDuration);
            holder.tvSinger=(TextView)convertView.findViewById(R.id.tvSinger);
            holder.tvAuthor=(TextView)convertView.findViewById(R.id.tvAuthor);
            convertView.setTag(holder);
        }
        holder=(ViewHolder)convertView.getTag();
        //给控件赋值
        Music music=musics.get(position);
        holder.tvName.setText(music.getName());
        holder.tvSinger.setText(music.getSinger());
        holder.tvAuthor.setText(music.getAuthor());
        holder.tvDuration.setText(music.getDurationtime());
        //给当前item中的ImageView设置一个Tag
        //用于图片下载完成后根据该tag
        //找到相应的ImageView
        holder.ivAlbum.setTag(position);
        //查询缓存中是否有图片 如果有 则直接获取
        SoftReference<Bitmap> ref=cache.get(music.getAlbumpic());
        if(ref!=null && ref.get()!=null){
            Bitmap bitmap=ref.get();
            holder.ivAlbum.setImageBitmap(bitmap);
            System.out.println("从缓存中读取图片..");
            return convertView;
        }
        //(3)下载一张图片  
        //向任务队列中添加一个图片任务
        ImageLoadTask task=new ImageLoadTask();
        //albumPic:   images/xxxxx.jpg
        task.path=music.getAlbumpic();
        task.position=position;
        tasks.add(task);
        //(4)唤醒工作线程  起来干活
        notifyWorkThread();
        return convertView;
    }
    /**
     * 唤醒工作线程
     */
    public void notifyWorkThread(){
    //注意:一但调用wait活notify方法的时候,就要在这个同步代码块对象上加锁
        synchronized (workThread) {
            workThread.notify();
        }
    }

    //(1)创建图片下载任务类型的类
    class ImageLoadTask{
        String path;//图片路径
        Bitmap bitmap;//图片对象
        int position; 
    }

    class ViewHolder{
        ImageView ivAlbum;
        TextView tvName;
        TextView tvDuration;
        TextView tvSinger;
        TextView tvAuthor;
    }

    public void stopWorkThread() {
        isLoop=false;
        notifyWorkThread();
    }
}

图片压缩

图片压缩的意义:(像一些小图标,不需要很高清)
例如我们写的上面的程序图片都是从服务器端下载下来的,一个图片大小是5k,但是这个5k的图片加载到内存里就不止是5k了,一个Bitmap肯定比5k要多(5k的十倍)50k,10张就500k(半兆),这样图片多了的话就非常浪费内存,占用内存!当占用内存十分大的时候,android 手机就会出现GC(垃圾回收机制),自动销毁堆内存中的垃圾。如果java管理的内存越来越满,快溢出了,GC执行频率会上升,导致效果:在GC执行垃圾回收的时候,所有的线程暂停,主线程也不准绘制UI!如果GC执行频率非常频繁,肯定会出现吊帧,卡顿的现象!

Bitmap图片(位图对象):

BitmapFactory 图片工厂:

Options封装了创建Bitmap对象时使用的参数

package com.tarena.musicclient.adapter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.activity.R;
import com.tarena.musicclient.entity.Music;
import com.tarena.musicclient.util.BitmapUtils;
import com.tarena.musicclient.util.GlobalConsts;
import com.tarena.musicclient.util.HttpUtils;

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;

public class MusicAdapter extends BaseAdapter{
    private Context context;
    private List<Music> musics;
    private LayoutInflater inflater;
    //声明任务集合  
    private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
    private ListView listView;
    //声明用于轮循任务集合的工作线程
    private Thread workThread;
    //声明Handler  更新ImageView
    private Handler handler=new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case HANDLER_LOAD_IMAGE_SUCCESS:
                //给ImageView设置Bitmap
                ImageLoadTask task=(ImageLoadTask)msg.obj;
                //通过tag寻找到相应的ImageView
                ImageView ivAlum=(ImageView)listView.findViewWithTag(task.position);
                if(ivAlum!=null){
                    if(task.bitmap!=null){
                        ivAlum.setImageBitmap(task.bitmap);
                    }else{
                        ivAlum.setImageResource(R.drawable.ic_launcher);
                    }
                }
                break;
            }
        }
    };

    public static final int HANDLER_LOAD_IMAGE_SUCCESS=0;


    public MusicAdapter(Context context, List<Music> musics, ListView listView) {
        this.context=context;
        this.musics=musics;
        this.listView=listView;
        inflater=LayoutInflater.from(context);
        //对workThread进行初始化
        workThread=new Thread(){
            public void run() {
                //不断轮循任务集合
                while(true){
                    //如果任务集合不是空集  
                    if(!tasks.isEmpty()){
                        //获取任务对象并且发送请求 
                        ImageLoadTask task = tasks.remove(0);
                        Bitmap bitmap=loadBitmap(task.path);
                        task.bitmap=bitmap;
                        //给相应的ImageView设置Bitmap   handler
                        Message msg=new Message();
                        msg.what=HANDLER_LOAD_IMAGE_SUCCESS;
                        msg.obj=task;
                        handler.sendMessage(msg);
                    }else{
                        synchronized (workThread) {
                            //如果任务集合是空集  wait等待
                            try {
                                workThread.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        };
        workThread.start();
    }

    /**
     * 通过path  获取Bitmap
     * @param path
     * @return
     */
    public Bitmap loadBitmap(String path){
        Bitmap bitmap=null;
        String uri=GlobalConsts.BASEURL+path;
        try {
            HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, uri, null);
            byte[] bytes=EntityUtils.toByteArray(entity);
            /**
             *图片压缩处理,工具类工具方法(传个来字节数字,和宽度、高度)
             **/
            bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    public int getCount() {
        return musics.size();
    }

    public Object getItem(int position) {
        return musics.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder=null;
        if(convertView==null){
            convertView=inflater.inflate(R.layout.item_lv_music, null);
            holder=new ViewHolder();
            holder.ivAlbum=(ImageView)convertView.findViewById(R.id.imageView1);
            holder.tvName=(TextView)convertView.findViewById(R.id.tvName);
            holder.tvDuration=(TextView)convertView.findViewById(R.id.tvDuration);
            holder.tvSinger=(TextView)convertView.findViewById(R.id.tvSinger);
            holder.tvAuthor=(TextView)convertView.findViewById(R.id.tvAuthor);
            convertView.setTag(holder);
        }
        holder=(ViewHolder)convertView.getTag();
        //给控件赋值
        Music music=musics.get(position);
        holder.tvName.setText(music.getName());
        holder.tvSinger.setText(music.getSinger());
        holder.tvAuthor.setText(music.getAuthor());
        holder.tvDuration.setText(music.getDurationtime());
        //给当前item中的ImageView设置一个Tag
        //用于图片下载完成后根据该tag
        //找到相应的ImageView
        holder.ivAlbum.setTag(position);

        //下载一张图片  
        //向任务队列中添加一个图片任务
        ImageLoadTask task=new ImageLoadTask();
        //albumPic:   images/xxxxx.jpg
        task.path=music.getAlbumpic();
        task.position=position;
        tasks.add(task);
        //唤醒工作线程  起来干活
        notifyWorkThread();
        return convertView;
    }
    /**
     * 唤醒工作线程,起来运行跳出循环
     */
    public void notifyWorkThread(){
        synchronized (workThread) {
            workThread.notify();
        }
    }


    class ImageLoadTask{
        String path;
        Bitmap bitmap;
        int position;
    }

    class ViewHolder{
        ImageView ivAlbum;
        TextView tvName;
        TextView tvDuration;
        TextView tvSinger;
        TextView tvAuthor;
    }
}

图片压缩工具类

package com.tarena.musicclient.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;

public class BitmapUtils {

    /**
     * 通过字节数组解析出Bitmap对象
     * 需要按照一定的宽高的规格进行压缩
     * @param bytes  数据源
     * @param width  图片的目标宽度
     * @param height  图片的目标高度
     * @return
     */
    public static Bitmap loadBitmap(byte[] bytes, int width, int height) {
        Options opt=new Options();
        //设置是否仅仅加载边界属性
        opt.inJustDecodeBounds=true;
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
        //获取图片的原始的高度与宽度
        int w=opt.outWidth/width;
        int h=opt.outHeight/height;
        int scale=w>h ? w : h;
        //设置压缩比例
        opt.inSampleSize=scale;
        //再次进行解析Bitmap
        opt.inJustDecodeBounds=false;
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
    }

}

Android 内存泄漏

Android内存当中有垃圾对象,这些垃圾对象被占用了之后还不能被GC(垃圾回收机制回收)内存也不能重复利用,导致内存泄漏。
GC垃圾回收机制:
这里写图片描述

项目中内存泄漏中的地方:
这里写图片描述
解决方法:
在Activity生命周期方法中销毁的时候关闭当前线程,详情看上方代码

内存泄漏最常见的情况:
Thread
new Thread (){}.start()必须给出run方法执行完毕的条件,在应用程序退出的时候销毁工作线程。

查看本程序中运行的线程

这里写图片描述

Java中的引用

强引用: StrongReference
e=new Emp();
就算出OOM,也不会销毁强引用
软引用: SoftReference
弱java管理的内存接近阈值,将会销毁一些软引用。释放内存
弱引用: WeakReference
就算java管理的内存没有接近阈值,就会销毁一些弱引用。
虚引用: …………
由GC管理的。

软引用的使用:
SoftReference s=new SoftReference(bitmap);
Bitmap bitmap=s.get();

Android图片的内存缓存

第一次把图片下载到手机后,存入内存中,再次需要下载图片时,先去内存中查询,如果已经下载过,那么直接获取,如果没有获取过,再去下载。
存:
注意:
一直存会容易c内存溢出OOM
HashMap < String,Bitmap > cache ;
cache.put(“images/jsjs.jpg”,bitmap);
cache.put(“images/jsjs.jpg”,bitmap);
cache.put(“images/jsjs.jpg”,bitmap);
cache.put(“images/jsjs.jpg”,bitmap);
cache.put(“images/jsjs.jpg”,bitmap);
WeakHashMap:
弱引用,当java的内存达到阈值的时候,会随机删除键值对。
取:
Bitmap bitmap=cache.get(“images/jsjs.jpg”);
改进后:
HashMap < String,SoftReference> map;
map.put(path,new SoftReference(bitmap));
map.get(path).get();
代码参考上方例子

图片的文件缓存

(1)下载图片后,把图片数据保存到应用的缓存目录中。

public void save(File targetFile,Bitmap bitmap)//工具类存的方法

Bitmap bitmap;
FileOutputStream fos;//写出到文件
file.write();
//缓存目录都存到cach文件中
bimap.compress();//压缩方法

(2)再次获取图片时,先去内存缓存中去查询,如果没有则去缓存目录中查询。有则直接读取。没有的话再次发送请求。

public Bitmap loadBitmap(path)//工具类方法:通过路径加载bitmap,也可以出入压缩的比例

String path;
BitmapFactory.decodeFile(path,Options);

文件缓存工具类方法:

package com.tarena.musicclient.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;

public class BitmapUtils {

    /**
     * 通过一个文件路径  查找到Bitmap
     * @param path
     * @return
     * @throws IOException
     */
    public static Bitmap  loadBitmap(String path)throws IOException{
        File file=new File(path);
        if(file.exists()){
            return BitmapFactory.decodeFile(path);
        }
        return null;
    }

    /***
     * 保存图片
     * @param targetFile  目标文件
     * @param bitmap  位图对象
     * @throws IOException  
     */
    public static void save(File targetFile, Bitmap bitmap)throws IOException{
        if(!targetFile.getParentFile().exists()){
            //父目录不存在 则创建
            targetFile.getParentFile().mkdirs();
        }
        if(!targetFile.exists()){
            targetFile.createNewFile();
        }
        //写入
        FileOutputStream fos=new FileOutputStream(targetFile);
        bitmap.compress(CompressFormat.JPEG, 100, fos);
    }

    /**
     * 通过字节数组解析出Bitmap对象
     * 需要按照一定的宽高的规格进行压缩
     * @param bytes  数据源
     * @param width  图片的目标宽度
     * @param height  图片的目标高度
     * @return
     */
    public static Bitmap loadBitmap(byte[] bytes, int width, int height) {
        Options opt=new Options();
        //设置是否仅仅加载边界属性
        opt.inJustDecodeBounds=true;
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
        //获取图片的原始的高度与宽度
        int w=opt.outWidth/width;
        int h=opt.outHeight/height;
        int scale=w>h ? w : h;
        //设置压缩比例
        opt.inSampleSize=scale;
        //再次进行解析Bitmap
        opt.inJustDecodeBounds=false;
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
    }

}

使用:

package com.tarena.musicclient.adapter;

import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.activity.R;
import com.tarena.musicclient.entity.Music;
import com.tarena.musicclient.util.BitmapUtils;
import com.tarena.musicclient.util.GlobalConsts;
import com.tarena.musicclient.util.HttpUtils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
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;

public class MusicAdapter extends BaseAdapter{
    private Context context;
    private List<Music> musics;
    private LayoutInflater inflater;
    //声明任务集合  
    private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
    private ListView listView;
    //声明用于轮循任务集合的工作线程
    private Thread workThread;
    //声明变量控制while循环
    private boolean isLoop=true;
    //声明缓存集合
    private HashMap<String, SoftReference<Bitmap>> cache 
        =new HashMap<String, SoftReference<Bitmap>>();

    //声明Handler  更新ImageView
    private Handler handler=new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case HANDLER_LOAD_IMAGE_SUCCESS:
                //给ImageView设置Bitmap
                ImageLoadTask task=(ImageLoadTask)msg.obj;
                //通过tag寻找到相应的ImageView
                ImageView ivAlum=(ImageView)listView.findViewWithTag(task.position);
                if(ivAlum!=null){
                    if(task.bitmap!=null){
                        ivAlum.setImageBitmap(task.bitmap);
                    }else{
                        ivAlum.setImageResource(R.drawable.ic_launcher);
                    }
                }
                break;
            }
        }
    };

    public static final int HANDLER_LOAD_IMAGE_SUCCESS=0;


    public MusicAdapter(Context context, List<Music> musics, ListView listView) {
        this.context=context;
        this.musics=musics;
        this.listView=listView;
        inflater=LayoutInflater.from(context);
        //对workThread进行初始化
        workThread=new Thread(){
            public void run() {
                //不断轮循任务集合
                while(isLoop){
                    //如果任务集合不是空集  
                    if(!tasks.isEmpty()){
                        //获取任务对象并且发送请求 
                        ImageLoadTask task = tasks.remove(0);
                        Bitmap bitmap=loadBitmap(task.path);
                        task.bitmap=bitmap;
                        //给相应的ImageView设置Bitmap   handler
                        Message msg=new Message();
                        msg.what=HANDLER_LOAD_IMAGE_SUCCESS;
                        msg.obj=task;
                        handler.sendMessage(msg);
                    }else{
                        synchronized (workThread) {
                            //如果任务集合是空集  wait等待
                            try {
                                workThread.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        };
        workThread.start();
    }

    /**
     * 通过path  获取Bitmap
     * @param path
     * @return
     */
    public Bitmap loadBitmap(String path){
        Bitmap bitmap=null;
        String uri=GlobalConsts.BASEURL+path;
        try {
            HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, uri, null);
            byte[] bytes=EntityUtils.toByteArray(entity);
            bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
            //向缓存集合中存储缓存图片
            cache.put(path, new SoftReference<Bitmap>(bitmap));
            //向文件缓存中存储图片
            //cacheDir:  /data/data/com.xxx.client/cache/
            //path: images/xxxx.jpg
            File targetFile=new File(context.getCacheDir(), path);
            BitmapUtils.save(targetFile, bitmap);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    public int getCount() {
        return musics.size();
    }

    public Object getItem(int position) {
        return musics.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder=null;
        if(convertView==null){
            convertView=inflater.inflate(R.layout.item_lv_music, null);
            holder=new ViewHolder();
            holder.ivAlbum=(ImageView)convertView.findViewById(R.id.imageView1);
            holder.tvName=(TextView)convertView.findViewById(R.id.tvName);
            holder.tvDuration=(TextView)convertView.findViewById(R.id.tvDuration);
            holder.tvSinger=(TextView)convertView.findViewById(R.id.tvSinger);
            holder.tvAuthor=(TextView)convertView.findViewById(R.id.tvAuthor);
            convertView.setTag(holder);
        }
        holder=(ViewHolder)convertView.getTag();
        //给控件赋值
        Music music=musics.get(position);
        holder.tvName.setText(music.getName());
        holder.tvSinger.setText(music.getSinger());
        holder.tvAuthor.setText(music.getAuthor());
        holder.tvDuration.setText(music.getDurationtime());
        //给当前item中的ImageView设置一个Tag
        //用于图片下载完成后根据该tag
        //找到相应的ImageView
        holder.ivAlbum.setTag(position);
        Bitmap bitmap=getCacheBitmap(music.getAlbumpic());
        if(bitmap!=null){
            holder.ivAlbum.setImageBitmap(bitmap);
            return convertView;
        }
        //下载一张图片  
        //向任务队列中添加一个图片任务
        ImageLoadTask task=new ImageLoadTask();
        //albumPic:   images/xxxxx.jpg
        task.path=music.getAlbumpic();
        task.position=position;
        tasks.add(task);
        //唤醒工作线程  起来干活
        notifyWorkThread();
        return convertView;
    }

    private Bitmap getCacheBitmap(String path){
        //查询缓存中是否有图片 如果有 则直接获取
        SoftReference<Bitmap> ref=cache.get(path);
        if(ref!=null && ref.get()!=null){
            Bitmap bitmap=ref.get();
            System.out.println("从缓存中读取图片..");
            return bitmap;
        }
        //查询文件缓存
        File targetFile=new File(context.getCacheDir(), path);
        Bitmap bitmap;
        try {
            bitmap = BitmapUtils.loadBitmap(targetFile.getAbsolutePath());
            //如果文件中查到了bitmap  
            //那么存入内存缓存
            if(bitmap!=null){
                System.out.println("从文件缓存中读取图片..");
                cache.put(path, new SoftReference<Bitmap>(bitmap));
            }
            return bitmap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;  
    }

    /**
     * 唤醒工作线程
     */
    public void notifyWorkThread(){
        synchronized (workThread) {
            workThread.notify();
        }
    }


    class ImageLoadTask{
        String path;
        Bitmap bitmap;
        int position;
    }

    class ViewHolder{
        ImageView ivAlbum;
        TextView tvName;
        TextView tvDuration;
        TextView tvSinger;
        TextView tvAuthor;
    }

    public void stopWorkThread() {
        isLoop=false;
        notifyWorkThread();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章