开发者

How to solve the vm budget memory heap error in lazy loading bitmaps?

I have been using Image loader class for lazy loading in list view. It works fine but I have been dealing with lots of bitmap that will be downloaded from web service. so now I get bitmap size exceeds VM budget. Increased bitmapfactory size to be 32*1024 but if it reaches 32mb again it will throw a the error. It being breaking my head for the past one week. so some one please help me out of this problem. I here by post my image loader class as well please let me know where and how should I solve this problem.

public class ImageLoader {

private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();
Bitmap bitmap = null;

private Activity activity;
PhotosLoader photoLoaderThread=new PhotosLoader();
public ImageLoader(Activity activity){
    this.activity = activity;
    photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
    clearCache();
}
public void DisplayImage(String url, Activity activity, ImageView imageView, String[] imageUrl){
    this.activity = activity;
    if(cache.containsKey(url)){
        imageView.setImageBitmap(cache.get(url));

    }
else{
        imageView.setImageResource(R.drawable.icon);
        queuePhoto(url, activity, imageView);
    }    

}

private void queuePhoto(String url, Activity activity, ImageView imageView){
    this.activity = activity;
    photosQueue.Clean(imageView);
    PhotoToLoad p=new PhotoToLoad(url, imageView);
    synchronized(photosQueue.photosToLoad){
        photosQueue.photosToLoad.push(p);
        photosQueue.photosToLoad.notifyAll();
    }
    if(photoLoaderThread.getState()==Thread.State.NEW)
        photoLoaderThread.start();
}

public Bitmap getBitmap(String url, int sampleSize) throws Exception{
    Bitmap bm = null;
    try {
        URL request = new URL(url);
        InputStream is = (InputStream) request.getContent();
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inDither = true;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inSampleSize = sampleSize;
        options.inTempStorage = new byte[32 * 1024];

        bm = BitmapFactory.decodeStream(is, null, options);
        if (bm!=null)
        bm = Bitmap.createScaledBitmap(bm, 115,100, true);
        is.close();
        is = null;
    } catch (IOException e) {
        throw new Exception();
    } catch (OutOfMemoryError e) {
        bm.recycle();
        bm = null;
        System.gc();
        throw new Exception();
    }
    return bm;
}
private class PhotoToLoad{
    public String url;
    public ImageView imageView;
    public PhotoToLoad(String u, ImageView i){
        url=u; 
        imageView=i;
    }
}
PhotosQueue photosQueue=new PhotosQueue();
public void stopThread(){
    photoLoaderThread.interrupt();
}
static class  PhotosQueue{
    private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
    public void Clean(ImageView image){
        for(int j=0 ;j<photosToLoad.size();){
            try{
            if(photosToLoad.get(j).imageView==image)
                photosToLoad.remove(j);
            else
                ++j;
            }catch (Exception e) {
            }
        }
    }
}
class PhotosLoader extends Thread {
    public void run() {
        try {
            while(true){

                if(photosQueue.photosToLoad.size()==0)
                    synchronized(photosQueue.photosToLoad){
                        photosQueue.photosToLoad.wait();
                    }
                if(photosQueue.photosToLoad.size()!=0){
                    PhotoToLoad photoToLoad;
                    synchronized(photosQueue.photosToLoad){
                        photoToLoad=photosQueue.photosToLoad.pop();
                    }
                    Bitmap bmp = null;
                        bmp = getBitmap(photoToLoad.url, 1);
                    cache.put(photoToLoad.url, bmp);
                    if(((String)photoToLoad.imageView.getTag()).equals(photoToLoad.url)){
                        BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
                        Activity a=(Activity)photoToLoad.imageView.getContext();
                        a.runOnUiThread(bd);
                    }
                }
                if(Thread.interrupted())
                    break;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class BitmapDisplayer implements Runnable{
    ImageView imageView;
    public  BitmapDisplayer(Bitmap b, ImageView i){
        bitmap = null;
        bitmap=b;
        imageView=i;
        }
    public void run(){
        if(bitmap!=null){
            imageView.setImageBitmap(bitmap);
            imageView.setScaleType(ScaleType.FIT_XY);
        }
        else{
            imageView.setImageResource(R.drawable.icon);
        }
    }
}

public void clearCache() {
    try{
    cache.clear();
    cache = new HashMap<String, Bitmap>();
    bitmap.recycle();   
    System.gc();
    }catch (Exception e) {
    开发者_C百科}
}


Quite simply you're trying to use more memory than the Android VM gives you. So you need to use less.

You either:

(1) need to manually clear your in-memory cache - i.e. once you reach a certain size or number of images

or alternatively

(2) use a HashMap of type <String, SoftReference<Bitmap>> so that the garbage collector can automatically reclaim the memory when the images are no longer being displayed.

With either of these methods your in-memory cache should not get as large as before (which is good), so you may want to save your files to disk so they do not have to be downloaded again should they be cleared from the in-memory cache.


verify below links..u can get idea about that...

http://negativeprobability.blogspot.com/2011/08/lazy-loading-of-images-in-listview.html http://stackoverflow.com/questions/5082703/android-out-of-memory-error-with-lazy-load-images http://blog.jteam.nl/2009/09/17/exploring-the-world-of-android-part-2/ http://groups.google.com/group/android-developers/browse_thread/thread/bb3c57cab27e0d91?fwc=1


Try like this..

try {
    HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
    conn.setDoInput(true);
    conn.connect();
    int length = conn.getContentLength();
    InputStream is = conn.getInputStream();

    bmImg = BitmapFactory.decodeStream(is);
    proImage.setImageBitmap(bmImg); // Bind image here on UI thread

    clearBitMap(bmImg); // Call to clear cache 
} 
catch (IOException e) {
    e.printStackTrace();
}


private void clearBitMap(Bitmap bitMap) {
    bitMap = null;
    System.gc();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜