当前位置:操作系统 > 安卓/Android >>

高效率下载图片——防止内存溢出

在应用中经常需要下载很多的图片,因此,写好图片下载部分的代码非常关键。不好的代码很容易创建太多的对象,导致经常执行GC,接着就出现了ANR;也很容易导致内存溢出OOM。
 
现在,我从防止ANR和OOM的角度写下载图片的代码。再来分析一下需求,当我需要为图片列表下载很多张图片时,我期望图片是有顺序地一张一张显示,而不是开启很多线程同时下载多张图片(注意:这样也会影响每个线程的执行速度)。
 
 
Java代码 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.os.Handler; 
import android.os.Message; 
 
public class ImageDownloadThread extends Thread { 
    //单例类 
    private ImageDownloadThread() {} 
    private static ImageDownloadThread imageDownloadThread = null; 
    public static ImageDownloadThread getInstance() { 
        if (imageDownloadThread == null) { 
            imageDownloadThread = new ImageDownloadThread(); 
            imageDownloadThread.start();//创建后立刻运行 
        } 
        return imageDownloadThread; 
    } 
     
    //缓存下载图片 
    private Map<String, String> cache = new HashMap<String, String>();//KEY:图片URL;VALUE:下载后的图片路径 
    public boolean isDownload(String imageUrl) { 
        return cache.containsKey(imageUrl); 
    } 
    public Bitmap downloadWithCache(ImageDownloadItem item) { 
        if (cache.containsKey(item.imageUrl)) { 
            Bitmap bitmap = BitmapFactory.decodeFile(cache.get(item.imageUrl)); 
            return bitmap; 
        } else { 
            addDownloadItem(item); 
        } 
        return null; 
    } 
    public void downloadWithoutCache(ImageDownloadItem item) { 
        addDownloadItem(item); 
    } 
 
    //下载队列 
    private List<ImageDownloadItem> queue = new ArrayList<ImageDownloadItem>(); 
    private synchronized void addDownloadItem(ImageDownloadItem item) { 
        queue.add(item); 
        this.notify();//添加了下载项就激活本线程 
    } 
 
    @Override 
    public void run() { 
        while(true) { 
            while(queue.size() > 0) { 
                ImageDownloadItem item = queue.remove(0); 
                String imagePath = downloadImage(item.imageUrl); 
                //缓存图片路径 
                cache.put(item.imageUrl, imagePath); 
 
                if (item.callback != null) {//需要执行回调来显示图片 
                    item.imagePath = imagePath; 
 
                    //交由UI线程处理 
                    Message msg = handler.obtainMessage(); 
                    msg.obj = item; 
                    handler.sendMessage(msg); 
                } 
            } 
            try { 
                synchronized(this) { 
                    this.wait();//没有下载项时等待 
                } 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
        } 
    } 
     
    private String downloadImage(String imageUrl) { 
        //TODO 
        //不提供该方法代码 
        //下载部分应该有专门下载文件的类(如:FileDownloadUtil.download(imageUrl)) 
        return ""; 
    } 
 
    private Handler handler = new Handler() { 
        @Override 
        public void handleMessage(Message msg) { 
            ImageDownloadItem item = (ImageDownloadItem)msg.obj; 
            Bitmap bitmap = BitmapFactory.decodeFile(item.imagePath); 
            item.callback.update(bitmap, item.imageUrl); 
        } 
    }; 
 
    public static class ImageDownloadItem { 
        public String imageUrl;//需要下载的图片URL 
        public String imagePath;//下载的后图片路径 
       

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,