AOS

[Android] 이미지 라이브러리(glide)없이 URL로 이미지 나타내기

유랄라- 2023. 5. 12. 21:54
반응형

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

 

반응형