본문 바로가기

Android(Kotlin) Study A부터 Z까지 등반

안드로이드 Glide란?

Glide

Glide란 무엇인가

  • 구글에서 밀고있는 이미지 로딩 라이브러리, Bump에서 만든건데 구글이 인수
  • 빠른 로딩을 위해 내부적으로 cache를 가짐

Glide 특징

  • Glide는 비디오 스틸, 이미지 및 애니메이션 GIF 가져오기, 디코딩 및 표시를 지원.
  • Glide에는 개발자가 거의 모든 네트워크 스택에 연결할 수 있는 유연한 API가 포함.
  • 기본적으로 Glide는 사용자 지정 HttpUrlConnection 기반 스택을 사용, Google의 Volley 프로젝트 또는 Square의 OkHttp 라이브러리에 플러그인하는 유틸리티 라이브러리도 포함.
  • Glide의 주요 초점은 모든 종류의 이미지 목록을 가능한 한 부드럽고 빠르게 스크롤하는 것
  • Glide는 원격 이미지를 가져오고, 크기를 조정하고, 표시해야 하는 거의 모든 경우에도 효과적.
  • Glide는 Bitmap포맷을 RGB_565를 사용한다고 함

 

💡 간단하게 설명하자면, 요청한 데이터가 먼저 캐시에 있는지 확인(있으면 바로 Return), 없으면 내부 저장소에서 불러오는지 확인(있으면 메모리에 올린 후 return), URL로 받아오는거면 Disk에 저장한 후 메모리에 올린 후에 Return

 

덜 간단하게 설명

  1. Active Resource
  • 사용하려는 이미지가 지금 다른 View에서 사용중인지 확인
  1. Memory Cache
  • 메모리 캐시가 이미지에 로드가 되었고, 여전히 메모리에 남아있는지 확인
  1. Resource
  • 사용하려는 이미지가 이전에 디코딩, 변환 및 디스크 캐시에 기록된 적이 있는지 확인
  1. Data
  • 사용하려는 이미지를 가져온 데이터가 이전에 디스크 캐시에 기록이 되어있는지 확인

4단계로 나뉘는데 각각 2단계씩 묶인다.

  • 1~2단계는 리소스가 메모리에 있는지 확인하고 남아있다면 그 즉시 이미지를 반환
  • 3~4단계는 이미지가 디스크에 있는지 확인하고 비동기식으로 빠르게 반환되는지 확인
  • 4단계 모두 이미지를 찾지 못하면 Glide는 원본 소스로 돌아가서 데이터를 검색 (File,Url 등등..)

정리하면

 

💡 Image -> Memory 체크 -> Disk 체크 -> 원본 image Load 순으로 진행

 

따라서 메모리 관리를 잘 해야할 것이다. 물론 Glide에서는 해결하는 메소드들이 정의 되어 있다고 한다.

  • skipMemoryCache(Boolean) 캐시에 저장 안할 때 true
  • diskCacheStrategy(DiskCacheStrategy strategy) : DiskCacheStrategy를 보내줄 때 옵션은 DATA, ALL → 여러번 사용하는데 disk에 저장할 때, NONE → 저장안할거면 이거를 보내면 된다.

Cache 무효화

  • 캐시에 데이터가 남아있어 이미지 업로드가 안 될때가 있다고 함
  • 해싱된 키 값이기 때문에 혹시라도 겹치는 경우가 생길 수도 있어 signiture를 달리주면 된다고 한다.
  • 보통 서버에서는 이미지를 바꿨지만 앱에서는 교체되지 않을 때 이런 현상을 신경쓴다.

해당 예제 생성 시간 등으로 signiture를 주면 된다고 함(MIME 유형, media store item의 orientation까지 혼합해서도 쓴다고함), 캐시 저장 x, disk 저장 x

  • 물론 더 있다. URL로 무효화, File로 무효화, key를 인터페이스로 구현 등
//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)
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());
}
}

API

Glide는 사용자가 한 줄에 대부분의 요청을 할 수 있도록 하는 간단한 방법으로 API를 사용.

사용방법

**Glide**.with(fragment)
    .load(url)
    .into(imageView);

placeHolder 이미지

왜 쓰는가? → 외부 URL 등에서 이미지를 받아올 때 잠깐의 버벅임이 있을 수도 있음, 그때 default 이미지를 보여주는 것

Error PlaceHolder도 있다. 로드 실패시 보여줄 이미지

예시 placeHolder

Glide.with(context)
     .load("<http://www.example.com/icon.png>")
     .placeholder(R.mipmap.ic_launcher)
     .into(target);

예시 erro

Glide.with(context)
     .load("<http://www.example.com/icon.png>")
     .placeholder(R.mipmap.ic_launcher)
     .erro(R.mipmap.ic_error)        //Error상황에서 보여진다.
     .into(target);

Animation - placeholder → 원본 이미지 보여줄 때 애니메이션, crossFade()가 on, dontAnimate()가 off

// Animation On
Glide.with(context)
     .load("<http://www.example.com/icon.png>")
     .placeholder(R.mipmap.ic_launcher)
     .erro(R.mipmap.ic_error)        //Error상황에서 보여진다.
     .crossFade()
     .into(target);

// Animation Off
Glide.with(context)
     .load("<http://www.example.com/icon.png>")
     .placeholder(R.mipmap.ic_launcher)
     .erro(R.mipmap.ic_error)        //Error상황에서 보여진다.
     .dontAnimate()
     .into(target);

성능

Glide는 Android에서 이미지 로드 성능의 두 가지 주요 측면을 고려해야한다.

  • 이미지를 디코딩할 수 있는 속도.
  • 이미지를 디코딩하는 동안 발생하는 버벅거림의 양.

💡 사용자가 앱에 대한 훌륭한 경험을 하려면 이미지가 빨리 나타나야 할 뿐만 아니라 메인 스레드 I/O 또는 과도한 가비지 수집으로 인한 버벅거림 및 버벅거림이 발생하지 않아야 함.

 

따라서 Glide는 Android에서 이미지 로드가 최대한 빠르고 원활하게 되도록 여러 단계를 수행한다고 함.

  • 자동 다운샘플링 및 캐싱은 스토리지 오버헤드와 디코딩 시간을 최소화합니다.
  • 바이트 배열 및 비트맵과 같은 리소스의 적극적인 재사용은 값비싼 가비지 수집 및 힙 조각화를 최소화합니다.
  • 깊은 수명 주기 통합을 통해 활성 프래그먼트 및 활동에 대한 요청만 우선 순위가 지정되고 애플리케이션은 백그라운드에서 종료되는 것을 방지하기 위해 필요할 때 리소스를 해제합니다.

요구사항

Minimum SDK Version - Glide requires a minimum SDK version of 14 (Ice Cream Sandwich) or higher.

Compile SDK Version - Glide must be compiled against SDK version 27 (Oreo MR1) or higher.

Support Library Version - Glide uses support library version 27.

다른 버전의 지원 라이브러리가 사용하려는 경우  "com.android.support"를 Glide 종속성에서 exclude해야 한다고 함.

지원 라이브러리의 v26을 사용하려는 경우:

dependencies {
  implementation ("com.github.bumptech.glide:glide:4.11.0") {
    exclude *group:* "com.android.support"
  }
  implementation "com.android.support:support-fragment:26.1.0"
}

코틀린에서 사용할 때

Kotlin에서 구현된 클래스에서 Glide의 주석을 사용 하는 경우 종속성 kapt대신 Glide의 주석 프로세서에 대한 종속성 을 포함해야 함 annotationProcessor.

dependencies {
  kapt 'com.github.bumptech.glide:compiler:4.11.0'
}

build.gradle파일에 kotlin-kapt플러그인도 포함해야 함.

apply *plugin:* 'kotlin-kapt'
  • URL에서 이미지를 가져올 경우 INTERNET및 ACCESS_NETWORK_STATE권한 추가
  • External_storage로 사용하는 경우 권한 추가 : **READ_EXTERNAL_STORAGE**