2012-09-25 7 views
-1

아래 URL 레시피를 사용하고 있습니다. 자주 응용 프로그램을 실행할 때 메모리 부족 문제 (OOM)가 발생합니다. 이미지를로드 할 수있는 업데이트 된 ImageLoader를 즉시 전송할 수 있습니까? 캐시에 저장하십시오. 미리 감사드립니다. 이 모든 괜찮아 경우 http://codehenge.net/blog/2011/06/android-development-tutorial-asynchronous-lazy-loading-and-caching-of-listview-images/안드로이드 리스트뷰에 더 많은 이미지로드하기

답변

0
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.URL; 
import java.util.HashMap; 
import java.util.Stack; 

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

public class ImageLoader { 

    // the simplest in-memory cache implementation. This should be replaced with 
    // something like SoftReference or BitmapOptions.inPurgeable(since 1.6) 
    private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>(); 

    private File cacheDir; 
    private Context ctx; 

    public ImageLoader(Context context) { 
     // Make the background thead low priority. This way it will not affect 
     // the UI performance 
     photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1); 
     ctx = context; 
     // Find the dir to save cached images 
     if (android.os.Environment.getExternalStorageState().equals(
       android.os.Environment.MEDIA_MOUNTED)) 
      cacheDir = new File(
        android.os.Environment.getExternalStorageDirectory(), 
        ".abcde"); 
     else 
      cacheDir = context.getCacheDir(); 
     if (!cacheDir.exists()) 
      cacheDir.mkdirs(); 
    } 

    final int stub_id = R.drawable.no_image; 

    public void DisplayImage(String url, Activity activity, ImageView imageView) { 
     if (cache.containsKey(url)) { 

      imageView.setImageBitmap(cache.get(url)); 
     } 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(); 
    } 

    public Bitmap getBitmap(String urlString) { 
     String filename = String.valueOf(urlString.substring(urlString 
       .lastIndexOf("/") + 1)); 
     File f = new File(cacheDir, filename); 
     try { 
      if (!f.exists()) { 
       Bitmap bitmap = null; 
       InputStream is = new URL(urlString).openStream(); 
       OutputStream os = new FileOutputStream(f); 
       Globals.CopyStream(is, os); 
       os.close(); 
       bitmap = decodeFile(f); 

       return bitmap; 
      } else { 
       Bitmap bitmap = decodeFile(f); 
       return bitmap; 
      } 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
      Log.e(Data.LOG, ex.getMessage(), ex); 
      Bitmap icon = BitmapFactory.decodeResource(ctx.getResources(), 
        R.drawable.no_image); 
      return icon; 
     } 
    } 

    // 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 = 70; 
      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++; 
      } 

      // 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 { 
     @Override 
     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 = getBitmap(photoToLoad.url); 
         cache.put(photoToLoad.url, bmp); 

         if (photoToLoad.url == null) { 

         } else { 

          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) { 
       // 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() { 

     cache.clear(); 

     // clear SD cache 
     File[] files = cacheDir.listFiles(); 
     for (File f : files) 
      f.delete(); 
    } 

} 
+0

내가 코드를 포맷했습니다 확인하세요! – Buffalo

+1

편집 해 주셔서 감사합니다 :) –

+0

예 그 지느러미가 있지만 자주 응용 프로그램을 실행할 때 그 해당 OutOfMemoryException (OOM), 비트 맵 재활용 것 같아요. 내 질문에 비트 맵 메모리를 다시 얻는 방법이며 안드로이드 LruCache에서 비트 맵을 자동으로 재활용 할 수 있습니까? – Ravikumar11

관련 문제