2016-09-16 6 views
0

내 앱에는 일부 미리보기 이미지가 포함 된 다른 목록보기가 있습니다. 오늘 리팩토링을 시작했으며 LRU 캐싱을 구현하려고합니다. 안드로이드 가이드 라인을 따르고 있지만 전체 애플 리케이션을 위해 단 하나의 LRU 캐시를 초기화하는 것이 더 나은지 궁금하거나 각리스트보기에서 LRU 캐시를 더 잘 초기화하는 것이 좋습니다. 나는 outOfMemory를 두려워합니다. 따라서 다음 질문에 답할 수 없습니다. - 싱글 톤 패턴으로 초기화 된 하나의 LRU 캐시가 좋은 아이디어입니까? - 메모리가 부족하면 outOfMemory 상황으로 인해 LRU 캐시가 다음과 같이 초기화됩니까? 메모리가 부족한 경우LRU 캐시 : 전체 앱에 대해 하나만 초기화 하시겠습니까?

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    ... 
    // Get max available VM memory, exceeding this amount will throw an 
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an 
    // int in its constructor. 
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

    // Use 1/8th of the available memory for this memory cache. 
    final int cacheSize = maxMemory/8; 

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in kilobytes rather than 
      // number of items. 
      return bitmap.getByteCount()/1024; 
     } 
    }; 
    ... 
} 
  • 의 LRU 캐시는 자동으로 해제된다? LRU 캐시 (메모리가 부족하여 응용 프로그램이 다운되는 경우)를 사용할 때 응용 프로그램에 메모리가 해제 될지 궁금합니다.

  • 전체 응용 프로그램에 대해 하나의 LRU 캐시 만 문제가 될 수 있습니까?

  • 전체 앱에 대해 둘 이상의 LRU 캐시가 문제가 될 수 있습니까?

답변

1

나는 많은 문제를 가지고 있었기 때문에 여기에서 유용한 답을 줄 수 있습니다.

메모리가 부족하면 LRU 캐시는 자동으로 해제됩니까? 나는 LRU 캐시 하지 자동으로 메모리를 해제합니다 LRU 캐시

를 사용하는 경우 응용 프로그램이 메모리를 해제하는 문제가있는 것인지 궁금하네요. 프로그래밍 방식으로 항목을 제거해야합니다.

전체 앱에 대해 하나의 LRU 캐시 만 문제가 될 수 있습니까?

전체 앱에 대해 둘 이상의 LRU 캐시가 문제가 될 수 있습니까?

LruCache 클래스는 키 유형 및 값 유형이있는 일반 클래스입니다. 내가 캐싱 할 각 객체 유형에 대해 하나의 LRU 캐시를 갖고 싶다고 말합니다. 당신은 내가 한 일을하고 있습니다 : Bitmap을 캐싱하고 String로 키잉하십시오.

단지 참고 사항 : bitmap.getByteCount()을 사용할 때주의하십시오. JavaDocs에서는 다음과 같이 말합니다.

KITKAT에서이 방법의 결과는 더 이상 비트 맵의 ​​메모리 사용을 결정하는 데 사용할 수 없습니다. getAllocationByteCount()을 참조하십시오.

나는 Bitmap에 대해 LRU 캐시를 사용하고있었습니다. Application.onTrimMemory()을 재정의하고이 메서드가 호출 될 때마다 캐시를 ​​지우는 것으로 충분하다고 생각했습니다.

또한 동일한 작업을 수행했으며 앱에서 사용할 수있는 힙 메모리의 비율에 따라 캐시 크기를 설정했습니다.

하지만 내 애플 리케이션이 메모리 부족 상태이고 앱이 메모리가 부족한 이미지를 다운로드하려고 할 때 BitmapFactory은 여전히 ​​Bitmap에 메모리를 할당 할 수 없습니다. 로그에 onTrimMemory() 메서드가 비동기식으로, 때로는 이 던져진 후 거의 1 초라고 불리는 것으로 나타났습니다!

은 GOOGLE HEY : 시스템은 내가OutOfMemoryError가 발생 후에 UNTIL 메모리가 부족 'M 말해봐 수없는 경우은 도대체 AM 나는 내 메모리를 관리하는데 어떻게?

정신 나간. 깎아 지른 광기.

여기에 내가하고 결국 무엇을 : 나는 try 블록캐치 OutOfMemoryError, 그럼 거기에 캐시를 지우 서버에 이미지 요청을 다시 시도합니다. 그들이 당신에게하지 말라고 말한 정확한 것. 그러나 그것은 결국 내 문제를 해결했다. 앱이 훨씬 안정적입니다.

LRU 캐시를 구현 한 후에는 앱 스트레스 테스트를 수행해야합니다. 메모리 부족 상황에 처하게하고 어떻게 동작하는지보십시오. 나를 위해 그것은 에뮬레이터를 사용할 때 가장 잘 작동했습니다. 에뮬레이터는 작은 96M 힙 제한을 가지지 만 화면 해상도가 높으면 이미지 리소스가 상당히 커져서 메모리를 최대한 쉽게 사용할 수 있습니다.

당신은 썸네일을 표시하고 있습니다,하지만 당신은 서버에서 이미지를 받고 있으며, 당신의 ImageView보다 큰이 문서 읽을 수 있는지 확인 수있는 경우 : 메모리를 낭비하지 않고 적절한 크기의 비트 맵을 다운로드하는 방법을 배울 수 Loading Large Bitmaps Efficiently | Android Developers을.

시스템에 캐싱을 수행하고 HttpResponseCache을 설정하는 것으로 실험 할 수도 있습니다.

무슨 일을 하던지, 앱에 스트레스를 가하고 많이 힙이 남지 않았을 때 어떻게 작동하는지 확인하십시오.

그리고 약간의 좌절을 대비해야합니다.

+0

안녕하세요! 이 시점에서 나는 listview 생성자에서 weakHashMap을 초기화하고 있는데, 그 맵에 축소판을 넣는다. 나는 그것이 LRU 캐시를 사용하는 것이 더 좋다고 생각했지만, 대답을 읽은 후에 나는 조금 겁이났다. – aeroxr1

+1

방금 ​​WeakHashMap을 보았다. 나는 그것이 그 클래스에서 약한 참조가 아닌 * 키 *라는 것을 깨닫지 못했다. 그런 이유로, 나는 Map >와 같은 맵을 만들고 싶을 것 같다. 나는 그 일을 처음부터 끝내기를 바랬다. 'LruCache' 클래스는 GC에 함축 된 암묵적인 관계가 없으므로, 거의 쓸모가 없습니다. 그래서 옳은 길에있을 수 있습니다. 그것의 쓰레기를 시험해라. 만일 그것이 받아 들일 만하게 행동하면, 승리를 선언하고, 그것을 하루라고 부른다. –

+0

약한 해시지도에서 약한 참조가있는 열쇠입니까 ??? 정말 ? 나는 이것을 몰랐다 !!! – aeroxr1