[Android] 이미지 라이브러리(glide)없이 URL로 이미지 나타내기
glide 는 android 에서 대부분 사용하는 이미지 라이브러리이다.
glide 는 기본적으로 비동기로 이미지를 로드하여 이미지뷰에 보여주고, 캐시처리를 해준다.
이러한 기능이 어떻게 동작하는지 glide 없이 직접 처리하여 공부해보자
1. 비동기 처리 ( 코루틴 )
⭐️ 비동기 처리가 필요한 이유?
네트워크를 통해 이미지를 가지고 오면서 시간이 소요된다.
이미지 다운로드를 Main thread(UI Thread)에서 구현한다면 화면이 멈춘다.
( Main Thread를 5초 이상 사용하면 ANR 이 발생한다. )
시간이 오래걸리는 작업은 별도의 Thread에서 처리하고 비동기적 처리해야한다.
Android는 네트워크를 사용하는 작업이 Main Thread 에서 처리하지 못하게 하고 있다.
별도의 Thread에서 처리하려면 AsyncTask 를 이용하거나 Threaed를 별도 생성하는 방법 등이 있다.
하지만 구글에서 AsyncTask를 deprecated 선언하고, 코루틴을 사용할 것을 추천하고 있다.
object ImageLoader {
fun loadImage(url: String, completed: (Bitmap?) -> Unit) {
// IO Thread 에서 처리
CoroutineScope(Dispatchers.IO).launch {
// 이미지 다운 작업
val bitmap = BitmapFactory.decodeStream(URL(url).openStream())
// Main Trhead 에서 처리
withContext(Dispatchers.Main) {
completed(bitmap)
}
}
}
}
IO Thread 에서 처리
이미지를 다운로드 받는 것은 네트워크를 사용하는 작업(IO 작업)이다.
Main Thread 에서 처리
이미지 다운이 완료되면 Main Thread로 전달해야한다.
2. 이미지 다운로드 오류가 발생할 경우
object ImageLoader {
fun loadImage(url: String, completed: (Bitmap?) -> Unit) {
// IO Thread 에서 처리
CoroutineScope(Dispatchers.IO).launch {
// 다운로드 오류 처리 (null 반환)
try{
// 이미지 다운 작업
val bitmap = BitmapFactory.decodeStream(URL(url).openStream())
// Main Trhead 에서 처리
withContext(Dispatchers.Main) {
completed(bitmap)
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
completed(null)
}
}
}
}
}
이미지 다운로드 오류가 발생할 경우 null 이 반환되도록 해야한다.
3. 이미지 캐시
⭐️ cache 처리가 필요한 이유?
같은 이미지를 매번 다운로드하려면 시간이 오래걸리고 비효율적이다.
cache 처리를 하여 bitmap을 미리 저장해두고 빠르게 접근하여 어플리케이션 성능을 향상시켜야 한다.
glide 는 기본적으로 cache 처리를 해준다.
하지만 glide 라이브러리를 사용하지 않을 경우 cache처리를 직접해줘야한다.
object ImageLoader {
val imageCache = mutableMapOf<String, Bitmap>()
fun loadImage(url: String, completed: (Bitmap?) -> Unit) {
// 캐시 메모리에 해당 url이 있는지 확인
if (imageCache.containsKey(url)) {
// 캐시 메모리에 저장된 bitmap 전달
completed(imageCache[url])
return
}
// IO Thread 에서 처리
CoroutineScope(Dispatchers.IO).launch {
// 다운로드 오류 처리 (null 반환)
try{
// 이미지 다운 작업
val bitmap = BitmapFactory.decodeStream(URL(url).openStream())
// bitmap을 캐시메모리에 저장
imageCache[url] = bitmap
// Main Trhead 에서 처리
withContext(Dispatchers.Main) {
completed(bitmap)
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
completed(null)
}
}
}
}
}
4. View에서 ImageLoader 사용하기
ImageLoader.loadImage(이미지URL){binding.image.setImageBitmap(it)}
https://developer.android.com/topic/performance/graphics/cache-bitmap?hl=ko
비트맵 캐싱 | Android 개발자 | Android Developers
단일 비트맵을 사용자 인터페이스(UI)에 로드하는 것은 간단하지만 한 번에 더 큰 이미지의 집합을 로드해야 하면 더 복잡해집니다. 많은 경우(ListView, GridView 또는 LruCache 클래스와 같은 구성요소
developer.android.com