2012-11-28 5 views
0

많이 검색했지만 실수가 어디인지 이해하지 못했습니다. 처음으로 내 앱에서 웹이없는 경우 웹에서 이미지를 가져오고 있습니다. 생성 된 데이터베이스에서 그물을 가져오고 있습니다. ImageLoader 클래스를 게시하고 메모리 클래스를 누른 다음 utils 클래스를 게시하려고합니다. 잘못된 것이 있으면 도움을 요청하십시오. 미리 감사드립니다.앱 내부에서 액세스 할 때 메모리 부족 캐시 오류가 발생했습니다.

public class ClassImageLoader { 

ClassMemoryCache memoryCache=new ClassMemoryCache(); 
ClassFileCache fileCache; 
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
ExecutorService executorService; 

public ClassImageLoader(Context context){ 
    fileCache=new ClassFileCache(context); 
    executorService=Executors.newFixedThreadPool(5); 
} 

final int stub_id=R.drawable.restlogobutton; 
public void DisplayImage(String url, ImageView imageView) 
{ 
    imageViews.put(imageView, url); 
    Bitmap bitmap=memoryCache.get(url); 

    if(bitmap!=null) 
     imageView.setImageBitmap(bitmap); 
    else 
    { 
     queuePhoto(url, imageView); 
     imageView.setImageResource(stub_id); 
    } 
} 

private void queuePhoto(String url, ImageView imageView) 
{ 
    PhotoToLoad p=new PhotoToLoad(url, imageView); 
    executorService.submit(new PhotosLoader(p)); 
} 

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); 
     conn.setInstanceFollowRedirects(true); 
     InputStream is=conn.getInputStream(); 
     OutputStream os = new FileOutputStream(f); 
     ClassUtils.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=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*=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; 
    } 
} 

class PhotosLoader implements Runnable { 
    PhotoToLoad photoToLoad; 
    PhotosLoader(PhotoToLoad photoToLoad){ 
     this.photoToLoad=photoToLoad; 
    } 

    public void run() { 
     if(imageViewReused(photoToLoad)) 
      return; 
     Bitmap bmp=getBitmap(photoToLoad.url); 
     memoryCache.put(photoToLoad.url, bmp); 
     if(imageViewReused(photoToLoad)) 
      return; 
     BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad); 
     Activity a=(Activity)photoToLoad.imageView.getContext(); 
     a.runOnUiThread(bd); 
    } 
} 

boolean imageViewReused(PhotoToLoad photoToLoad){ 
    String tag=imageViews.get(photoToLoad.imageView); 
    if(tag==null || !tag.equals(photoToLoad.url)) 
     return true; 
    return false; 
} 

//Used to display bitmap in the UI thread 
class BitmapDisplayer implements Runnable 
{ 
    Bitmap bitmap; 
    PhotoToLoad photoToLoad; 
    public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;} 
    public void run() 
    { 
     if(imageViewReused(photoToLoad)) 
      return; 
     if(bitmap!=null) 
      photoToLoad.imageView.setImageBitmap(bitmap); 
     else 
      photoToLoad.imageView.setImageResource(stub_id); 
    } 
} 

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

}

public class ClassMemoryCache { 

private Map<String, Bitmap> cache=Collections.synchronizedMap(
     new LinkedHashMap<String, Bitmap>(10,1.5f,true));//Last argument true for LRU ordering 
private long size=0;//current allocated size 
private long limit=1000000;//max memory in bytes 

public ClassMemoryCache(){ 
    //use 25% of available heap size 
    setLimit(Runtime.getRuntime().maxMemory()/4); 
} 

public void setLimit(long new_limit){ 
    limit=new_limit; 
} 

public Bitmap get(String id){ 
    if(!cache.containsKey(id)) 
     return null; 
    return cache.get(id); 
} 

public void put(String id, Bitmap bitmap){ 
    try{ 
     if(cache.containsKey(id)) 
      size-=getSizeInBytes(cache.get(id)); 
     cache.put(id, bitmap); 
     size+=getSizeInBytes(bitmap); 
     checkSize(); 
    }catch(Throwable th){ 
     th.printStackTrace(); 
    } 
} 

private void checkSize() { 
    if(size>limit){ 
     Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iterated 
     while(iter.hasNext()){ 
      Entry<String, Bitmap> entry=iter.next(); 
      size-=getSizeInBytes(entry.getValue()); 
      iter.remove(); 
      if(size<=limit) 
       break; 
     } 
    } 
} 

public void clear() { 
    cache.clear(); 
} 

long getSizeInBytes(Bitmap bitmap) { 
    if(bitmap==null) 
     return 0; 
    return bitmap.getRowBytes() * bitmap.getHeight(); 
} 

}

public class ClassUtils { 
public static void CopyStream(InputStream is, OutputStream os) 
{ 
    final int buffer_size=1024; 
    try 
    { 
     byte[] bytes=new byte[buffer_size]; 
     for(;;) 
     { 
      int count=is.read(bytes, 0, buffer_size); 
      if(count==-1) 
       break; 
      os.write(bytes, 0, count); 
     } 
    } 
    catch(Exception ex){} 
} 

은}

답변

0

// 코드에서이 메서드를 바꾸고 오류를 해결할 수 있는지 확신 할 수 없지만 시도해 볼 수 있는지 확인하십시오.

private Bitmap getBitmap(String url) 
    { 
     //I identify images by hashcode. Not a perfect solution, good for the demo. 
     String filename=String.valueOf(url.hashCode()); 
     File f=new File(cacheDir, filename); 

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

     //from web 
     try { 
      Bitmap bitmap=null; 
      InputStream is=new URL(url).openStream(); 
      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=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*=2; 
     } 

     //decode with inSampleSize 
     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inTempStorage = new byte[32*1024]; 
     o2.inSampleSize=scale; 
     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
    } catch (FileNotFoundException e) {} 
    return null; 
} 

확인 ImageLoaderClass이 링크 : http://code.google.com/p/vimeoid/source/browse/apk/src/com/fedorvlasov/lazylist/ImageLoader.java

OOM 문제가이 링크를 확인 : 당신은 여전히 ​​오류가 다음이 하나 개의 링크를 확인받을 경우 Strange out of memory issue while loading an image to a Bitmap object

을 그리고 나는 많은 후 발견 한 그 검색 및 내 문제를 해결했습니다 : https://groups.google.com/forum/?fromgroups=#!topic/android-developers/vYWKY1Y6bUo

+0

어떤 클래스에서 imageLoader 대신 모든 코드 대신 ur 코드를 대체 할 수 있습니까? –

+0

Iam sry i got you –

+0

Iam이 파일에 오류가 발생했습니다. f = new File (cacheDir, filename); 캐시에 왜 그 형제 야? –

1

메모리 관리는 매우 광범위하고 고급 주제하지만 난 대문자로 모두 매우 중요한 팁을 게시합니다 :

DO NOT USE MAP<k,v> !!!

맵은 액티비티 컨텍스트를 유지하는 이미지 뷰와 영원한 비트 맵에 대한 참조를 유지하며, 이러한 메모리 손실이 발생한 주된 이유 중 하나입니다. 문맥에 대한 참조는 당신의 모든 활동을 영원히 기억 속에 유지하는 것입니다. 아주 나쁜 아이디어.

당신은 비트 맵을 캐시, 만 활동을 수 있도록 (호환성 라이브러리시) LruCache를 사용합니다은 여기합니다 (XML에서 정적 또는 동적으로 어댑터를 사용 중)이 imageviews

에 대한 참조를 유지 구글 IO 비디오 http://www.youtube.com/watch?v=gbQb1PVjfqM 구글의 녀석들이이 지역의 모범 사례를 보여주고 있으며, 4 분에 LruCache 사용법을 보여줍니다.

+0

이 비디오는 완벽하지만 여전히 iam은 안드로이드에서 초보자 나는 그게 무슨 sai있어 하지만 내 코드가 정확히 어디에서 수정 해야할지 잘 모릅니다. 클래스가 모두 섞여 있지만 감사합니다. –

관련 문제