2013-01-19 62 views
4

Possible Duplicate:
Android: Strange out of memory issue while loading an image to a Bitmap object的Android的OutOfMemoryError:位圖大小超過VM預算,同時加載圖像

我使用它加載在爲我的文件系統從URL和緩存圖像的圖像裝載機。我發現從幾部電話使用ACRA

以下崩潰報告

錯誤:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493) 
    at com.m7.nomad.utils.ImageLoader.decodeFile(ImageLoader.java:117) 
    at com.m7.nomad.utils.ImageLoader.getBitmap(ImageLoader.java:88) 
    at com.m7.nomad.utils.ImageLoader.access$0(ImageLoader.java:68) 
    at com.m7.nomad.utils.ImageLoader$PhotosLoader.run(ImageLoader.java:170) 

ImageLoader.java

package com.m7.nomad.utils; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.util.Collections; 
import java.util.Map; 
import java.util.Stack; 
import java.util.WeakHashMap; 

import com.m7.nomad.R; 

import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.widget.ImageView; 

public class ImageLoader { 

    MemoryCache memoryCache = new MemoryCache(); 
    FileCache fileCache; 
    private Map<ImageView, String> imageViews = Collections 
      .synchronizedMap(new WeakHashMap<ImageView, String>()); 

    public ImageLoader(Context context) { 
     // Make the background thread low priority because it will not affect 
     // the 
     // UI performance 
     photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1); 

     fileCache = new FileCache(context); 
    } 

    final int stub_id = R.drawable.image_place_holder; 

    public void DisplayImage(String url, Activity activity, ImageView imageView) { 
     imageViews.put(imageView, url); 
     Bitmap bitmap = memoryCache.get(url); 
     if (bitmap != null) 
      imageView.setImageBitmap(bitmap); 
     else { 
      queuePhoto(url, activity, imageView); 
      imageView.setImageResource(stub_id); 
     } 
    } 

    private void queuePhoto(String url, Activity activity, ImageView imageView) { 
     // This ImageView may be used for other images before. So there may be 
     // some old tasks in the queue. We need to discard them. 
     photosQueue.Clean(imageView); 
     PhotoToLoad p = new PhotoToLoad(url, imageView); 
     synchronized (photosQueue.photosToLoad) { 
      photosQueue.photosToLoad.push(p); 
      photosQueue.photosToLoad.notifyAll(); 
     } 

     // start thread if it's not started yet 
     if (photoLoaderThread.getState() == Thread.State.NEW) 
      photoLoaderThread.start(); 
    } 

    private Bitmap getBitmap(String url) { 
     File f = fileCache.getFile(url); 

     // from SD cache 
     Bitmap b = decodeFile(f); 
     if (b != null) 
      return b; 

     // from web 
     try { 
      Bitmap bitmap = null; 
      URL imageUrl = new URL(url); 
      HttpURLConnection conn = (HttpURLConnection) imageUrl 
        .openConnection(); 
      conn.setConnectTimeout(30000); 
      conn.setReadTimeout(30000); 
      InputStream is = conn.getInputStream(); 
      OutputStream os = new FileOutputStream(f); 
      Utils.CopyStream(is, os); 
      os.close(); 
      bitmap = decodeFile(f); 
      return bitmap; 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 

    // decodes image and scales it to reduce memory consumption 
    private Bitmap decodeFile(File f) { 
     try { 
      // decode image size 
      BitmapFactory.Options o = new BitmapFactory.Options(); 
      o.inJustDecodeBounds = true; 
      BitmapFactory.decodeStream(new FileInputStream(f), null, o); 

      // Find the correct scale value. It should be the power of 2. 
      final int REQUIRED_SIZE = 65; 
      int width_tmp = o.outWidth, height_tmp = o.outHeight; 
      int scale = 1; 
      /* 
      * while (true) { if (width_tmp/2 < REQUIRED_SIZE || height_tmp/
      * 2 < REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale 
      * *= 2; } 
      */ 

      // decode with inSampleSize 
      BitmapFactory.Options o2 = new BitmapFactory.Options(); 
      o2.inSampleSize = scale; 
      return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
     } catch (FileNotFoundException e) { 
     } 
     return null; 
    } 

    // Task for the queue 
    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(); 
    } 

    // stores list of photos to download 
    class PhotosQueue { 
     private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>(); 

     // removes all instances of this ImageView 
     public void Clean(ImageView image) { 
      for (int j = 0; j < photosToLoad.size();) { 
       if (photosToLoad.get(j).imageView == image) 
        photosToLoad.remove(j); 
       else 
        ++j; 
      } 
     } 
    } 

    class PhotosLoader extends Thread { 
     public void run() { 
      try { 
       while (true) { 
        // thread waits until there are any images to load in the 
        // queue 
        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 = getBitmap(photoToLoad.url); 
         memoryCache.put(photoToLoad.url, bmp); 
         String tag = imageViews.get(photoToLoad.imageView); 
         if (tag != null && tag.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) { 
       // allow thread to exit 
      } 
     } 
    } 

    PhotosLoader photoLoaderThread = new PhotosLoader(); 

    // Used to display bitmap in the UI thread 
    class BitmapDisplayer implements Runnable { 
     Bitmap bitmap; 
     ImageView imageView; 

     public BitmapDisplayer(Bitmap b, ImageView i) { 
      bitmap = b; 
      imageView = i; 
     } 

     public void run() { 
      if (bitmap != null) 
       imageView.setImageBitmap(bitmap); 
      else 
       imageView.setImageResource(stub_id); 
     } 
    } 

    public void clearCache() { 
     memoryCache.clear(); 
     fileCache.clear(); 
    } 

} 

這是我如何調用ImageLoader的

ImageView image = new ImageView(getActivity()); 

     ImageLoader imgLoader = new ImageLoader(MainActivity.context); 
     imgLoader.DisplayImage(imagePath, new Activity(), image); 
+0

如何使用imagedownloader類調用你的url? –

+0

@MaheshKavathiya我已編輯我的問題與該代碼 –

+0

試試這個鏈接http://stackoverflow.com/a/14117007/1935890 –

回答

1

你堆意外不斷提升的根據Android

1比例放倒的網址加載,然後將其加載到您的視圖(活動) 縮減你可以使用下面的代碼圖像的圖像尺寸是由於圖像大小片段,將採取圖像和尺寸,並會導致縮小圖像

public static Bitmap getResizedBitmap(Bitmap image, int newHeight, int newWidth) { 
    int width = image.getWidth(); 
    int height = image.getHeight(); 
    float scaleWidth = ((float) newWidth)/width; 
    float scaleHeight = ((float) newHeight)/height; 
    // create a matrix for the manipulation 
    Matrix matrix = new Matrix(); 
    // resize the bit map 
    matrix.postScale(scaleWidth, scaleHeight); 
    // recreate the new Bitmap 
    Bitmap resizedBitmap = Bitmap.createBitmap(image, 0, 0, width, height, 
      matrix, false); 
    return resizedBitmap; 
} 
相關問題