본문 바로가기

안드로이드 Android

안드로이드 개발 (6) - Glide 캐시 처리

https://bumptech.github.io/glide/doc/caching.html#caching-in-glide

 

Glide v4 : Caching

Caching in Glide By default, Glide checks multiple layers of caches before starting a new request for an image: Active resources - Is this image displayed in another View right now? Memory cache - Was this image recently loaded and still in memory? Resourc

bumptech.github.io

위의 내용에 따라 정리를 해봤습니다. 

 

Glide는 요즘 안드로이드 개발자라면 꼭 반드시 사용하는 이미지 로딩 라이브러리 입니다. 빠르고 효율적으로 이미지를 불러오고 사용하기도 매우 수월해서 안드로이드 개발자 남녀노소 가리지 않고 많은 사랑을 받고 있습니다. 이 Glide의 캐시처리까지 잘 알아두면 매우 좋으므로 한번 정리를 해봤습니다.

 

글라이드 캐시 

캐시처리는 크게 4단계로 나뉩니다.

 

1. Active Resource 

- 사용하려는 이미지가 지금 다른 View에서 사용중인지 확인

 

2. Memory Cache 

- 메모리 캐시가 이미지에 로드가 되었고, 여전히 메모리에 남아있는지 확인

 

3.Resource 

- 사용하려는 이미지가 이전에 디코딩, 변환 및 디스크 캐시에 기록된 적이 있는지 확인

 

4. Data

- 사용하려는 이미지를 가져온 데이터가 이전에 디스크 캐시에 기록이 되어있는지 확인

 

4단계로 나뉘는데 각각 2단계를 묶어서 설명이 됩니다.

 -> 1~2단계는 리소스가 메모리에 있는지 확인하고 남아있다면 그 즉시 이미지를 반환 

 -> 3~4단계는 이미지가 디스크에 있는지 확인하고 비동기식으로 빠르게 반환되는지 확인

 -> 4단계 모두 이미지를 찾지 못하면 Glide는 원본 소스로 돌아가서 데이터를 검색 (File,Url 등등..)

 

정리하면 

Image -> Memory 체크 -> Disk 체크 -> 원본 image Load 순으로 진행이 됩니다.

 

캐시 키 

Glide 4 에서 모든 캐시 Key는 최소한 두가지 요소가 포함됩니다.

 

1) Load가 요청한 모델 (File,Uri,Url)

->커스텀 모델을 구현해야 하는 경우 hashCode() 와 equals()를 구현해야합니다.

2) 선택사항 Signture

 

위에서 설명을 했던 4단계 처리 과정 중,

1~3단계의 캐시 키에 다음과 같은 데이터들도 포함 됩니다.

 

1. 너비와 높이 

2. 선택사항 Transformation

3. 추가된 모든 Options

4. 요청 된 데이터 유형(Bitmap,Gif 등..)

 

Active Resource 및 Memory Ceche에 사용되는 키 options는 

비트맵 또는 기타 디코딩 시간 전용 매개 변수의 구성에 영향을 주는 것과 같이

메모리에 수용하기 위해 리소스 디스크 캐시에서 사용되는 키와 약간 다릅니다 .

디스크에서 디스크 캐시 키의 이름을 생성하기 위해
키의 개별 요소를 해시하여 단일 문자열 키를
만든 다음 디스크 캐시에서 파일 이름으로 사용합니다.

 

디스크 캐시 전략

 DiskCacheStrategy는 diskCacheStrategy메서드와

함께 개별 요청에 적용 할 수 있습니다.

Strategy로 다음과 같이 설정이 가능합니다. 

 

- load가 디스크 캐시를 사용 방지
- load를 사용하지 않은 원본데이터만 캐시
- load
에 의해 생성 되거나 변환된 썸네일 또는 둘 다 캐시하도록 선택 가능

기본 방식 AUTOMATIC은 로컬 및 원격 이미지에 대해 최적의 전략 사용합니다. 


1) AUTOMATIC 원격 이미지 (Ex: Uri 사용)
-원격 데이터를 다운로드 하는것은 디스크에 있는 데이터 크기를 조정하는 것에 비해
많은 비용이들기 때문에 load로 수정하지 않은 원본 데이터만 불러옴

2) AUTOMATIC 로컬 데이터
-썸네일사진의 크기 또는 유형을 생성해야하는 경우 원본 데이터를
검색하는 것이 저렴하기 때문에 변환된 썸네일만 저장

 

아래와 같이 사용하면 됩니다. 

Glide.with(iv.context).load(TEST_IMG).diskCacheStrategy(DiskCacheStrategy.ALL).into(iv)

3) 캐쉬 건너 뛰기

  // 1. 글라이드 기본 형태 사용법
    private fun default() {
        Glide.with(iv.context).load(TEST_IMG).into(iv)
    }
    // 2. 글라이드 디스크 캐시전략
    private fun diskCacheStrategy () {
        Glide.with(iv.context).load(TEST_IMG).diskCacheStrategy(DiskCacheStrategy.ALL).into(iv)
    }
    // 3. 오직 캐시에서만 이미지 불러오기
    //이미지가 메모리 캐시 또는 디스크 캐시에서 발견되면 load 되고 없다면 load가 실행되지 않습니다.
    private fun onlyRetrieveFromCache(){
        Glide.with(iv.context).load(TEST_IMG).onlyRetrieveFromCache(true).into(iv)
    }

    //메모리캐시 건너띄기 skipMemoryCache()
    // 디스크캐시 건너띄기 iskCacheStrategy(DiskCacheStrategy.NONE)
    // 둘다 건너띄기는 같이 쓰면됨
    // 일반적으로 캐시를 건너 뛰지 않는걸 권장.
    // 이미지를 검색, 디코딩 및 변환하여 새 썸네일을 만드는 것보다 캐시에서 이미지를 load하는 것이 빠름
    //아래는 둘다 건너띈 코드 
    private fun skipMemoryCache(){
        Glide.with(iv.context).load(TEST_IMG)
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.NONE).into(iv)
    }

 

4) DiskCache 직접 구현
기본 제공되는 옵션중에 원하는 옵션이 없을 때 자체적으로 DiskCache 구현을 통해 작성할 수도 있습니다.

 

캐시무효화

디스크 캐시는 해시 된 키이므로 특정 URL 또는 파일 경로에 해당하는
디스크의 모든 캐시 된 파일을 간단하게 삭제하는 좋은 방법은 없습니다.

원본 이미지를 load 하거나 캐시 할 수만 있으면 좋겠지만,
Glide는 변환된 결과를 캐싱하고 다양한 변환을 제공하기 때문에
캐시마다 새로운 파일이 생성되므로, 캐시된 이미지를 추적하여 삭제하는 것은 어렵습니다.

(실제로 캐시 파일을 무효화하는 가장 좋은 방법은 콘텐츠가 변경 될 때
(url, uri, 파일 경로 등) 식별자를 변경하는 것 입니다.)

커스텀 캐시 무효화


식별자 변경이 어렵거나 불가능한 경우가 많기 때문에 Glidesignature()를 제공합니다.
사용자가 제어하는추가 데이터를 캐시 키에 혼합 하는 API를 제공합니다.

1) Media Store Contents - GlideMediaStoreSignature클래스를 사용할 수 있습니다.
MediaStoreSignature 클래스는
-수정 한 날짜 시간,
-MIME 유형
-media store item orientation
등등을 캐시 키로 혼합 할 수 있습니다.

이 세가지 특성은 미디어 저장소를 캐시하기 위해 수정과 업데이트를 안정적으로 캐치합니다.

2) File - ObjectKey파일의 날짜 수정 시간을 혼합 하는 데 사용할 수 있습니다.

3) URL- URL을 무효화하는 가장 좋은 방법은 URL의 콘텐츠가 변경 될 때
서버가 URL을 변경하고 클라이언트를 업데이트하도록하는 것이지만,
ObjectKey로 임의의 데이터를 혼합 하는 데 사용할 수도 있습니다.
(ex: 버전 번호 혼합)


//sinature를 포함 시키는법
Glide.with(imageView)
.load(uri)
.signature(new ObjectKey(yourVersionMetadata))
.into(imageView)
//Media Store sinature 포함

Glide.with(imageView)
.load(uri)
.signature(new MediaStoreSignature(mimeType, dateModified, orientation))
.into(imageView)


4) Key인터페이스 를 구현하여 고유 한 서명을 정의 할 수도 있습니다.
equals(), hashCode(), updateDiskCacheKey()
등등을 구현해야합니다

public class IntegerVersionSignature implements Key {
private int currentVersion;

public IntegerVersionSignature(int currentVersion) {
this.currentVersion = currentVersion;
}

@Override
public boolean equals(Object o) {
if (o instanceof IntegerVersionSignature) {
IntegerVersionSignature other = (IntegerVersionSignature) o;
return currentVersion == other.currentVersion;
}
return false;
}

@Override
public int hashCode() {
return currentVersion;
}

@Override
public void updateDiskCacheKey(MessageDigest md) {
messageDigest.update(ByteBuffer.allocate(Integer.SIZE).putInt(signature).array());
}
}


성능 저하를 방지하려면 이미지를 로드하려고 할 때
사용할 수 있도록 백그라운드에서 버전 관리 메타 데이터를 일괄로드하는 것이 좋습니다.

다른 모든 실패하고 둘 다 당신의 ID를 변경하거나
임의 합리적인 버전 메타 데이터를 추적 할 수 있다면,
당신은 또한 비활성화 디스크 캐싱을 완전히 사용 가능합니다.
( diskCacheStrategy(), DiskCacheStrategy.NONE.)


자원 관리

-Glide의 디스크 및 메모리 캐시는 LRU입니다.


- , 한계에 도달하거나 한계에 근접하여 계속 사용할 한계에 도달 할 때까지
  점점 더 많은 메모리 및 / 또는 디스크 공간을 차지합니다.


유연성을 위해 Glide는 애플리케이션에서 사용하는 리소스를
관리 할 수있는 몇 가지 추가 방법을 제공합니다.

메모리 캐시, Bitmap Pool 및 디스크 캐시는
일반적으로 적어도 어느 정도까지는 약간 더 나은 성능을 제공합니다.


캐시 크기를 변경하는 경우 성능 / 크기 절충이 합리적인지 확인하기
위해 변경 전후의 성능을 신중하게 측정해야합니다.


1) 메모리 캐시


기본적으로 Glide의 메모리 캐시는 프레임 워크가 제공하는 수준에 따라
다양한 수준으로 콘텐츠에 BitmapPoolComponentCallbacks2에 응답
하고 자동으로 제거합니다.
따라서 일반적으로 캐시 또는 BitmapPool를 동적으로
모니터링하거나 지울 필요가 없습니다
그러나 필요한 경우 Glide는 몇 가지 수동 옵션을 제공합니다.

-전체 크기 변경
애플리케이션 전체에서 Glide에 사용할 수 있는
RAM의 양을 변경하려면
https://bumptech.github.io/glide/doc/configuration.html#memory-cache 를 참고하면됩니다.

-일시적인 크기 변경.
Glide가 앱의 특정 부분에서 더 많거나 적은 메모리를 일시적으로
사용하도록 허용하려면 다음을 사용할 수 있습니다

Glide.get(context).setMemoryCategory(MemoryCategory.LOW);
//혹은
Glide.get(context).setMemoryCategory(MemoryCategory.HIGH);
//앱의 메모리 또는 성능에 민감한 영역을 떠날 때 메모리 범주를 다시 재설정해야합니다.
Glide.get(context).setMemoryCategory(MemoryCategory.NORMAL);



-메모리 지우기
Glide의 메모리 캐시를 지우려면 다음을 BitmapPool사용하십시오

clearMemory.
*메인스레드 실행해야함 

// This method must be called on the main thread.
Glide.get(context).clearMemory();

모든 메모리를 지우는 것은 특히 효율적이지 않으며
버벅거림 및 loading 시간 증가를 피하려면 가능한 한 피해야합니다.


2) 디스크 캐시


Glide는 런타임에 디스크 캐시 크기에 대한 제한된 조작만 제공하지만
AppGlideModule에서 크기와 구성을 변경할 수 있다.

-영구적 인 크기 변경
애플리케이션 전체에서 Glide의 디스크 캐시에 사용할 수 있는 sdcard 공간을 변경하려면
https://bumptech.github.io/glide/doc/configuration.html#disk-cache>를 참조 하세요.

-디스크 캐시 지우기
디스크 캐시의 모든 항목을 지우려면 다음을 사용할 수 있습니다
** 아래 메서드는 백그라운드를 통해 호출이 되어야 합니다.

// This method must be called on a background thread.
Glide.get(applicationContext).clearDiskCache();