안드로이드에서 Glide, Picasso, Coil 등 선택할 수 있는 이미지 라이브러리(Image library)의 폭은 넓다. 뭐 대부분 그냥 닥치고 글라이드! 하긴하지만, 메모리 관리 측면에서 누가 젤 잘하는지 항상 속으로 궁금했다... 주말에 심심하니까 간단히 테스트 해봤다.
비교군
- Glide: 1군
- Picasso: 2인자
- Coil: 떠오르는 신예
앱 기능
앱 자체는 간단하다. 화면 하나에 엄청나게 큰 이미지 목록을 보여주는거다.
RecyclerView에 Adapter를 붙이고 로드! Coil 같은 경우에는 이미지 곡선처리하는데 이미지뷰 자체가 아닌 이미지 자체를 곡선처리 해버려서 모든 라이브러리가 곡선처리는 따로 하지 않도록 RoundedImageView라는 라이브러리를 사용하여 이미지에 라운딩 값을 주었다.
실무에서 곡선처리 할일이 많으니...기본적으로 적용했다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var imageAdapter: ImageAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
imageAdapter = ImageAdapter()
binding.recyclerView.setHasFixedSize(true)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = imageAdapter
val imageList = listOf(
"https://wallpapershome.com/images/pages/pic_h/22741.jpg",
"https://wallpapershome.com/images/pages/pic_h/18952.jpg",
"https://wallpapershome.com/images/pages/pic_h/22312.jpg",
"https://wallpapershome.com/images/pages/pic_h/22790.jpg",
"https://wallpapershome.com/images/pages/pic_h/22746.jpg",
"https://wallpapershome.com/images/pages/pic_h/22749.jpg",
"https://wallpapershome.com/images/pages/pic_h/20322.jpg",
"https://wallpapershome.com/images/pages/pic_h/22740.jpg",
"https://wallpapershome.com/images/pages/pic_h/22796.jpg",
"https://wallpapershome.com/images/pages/pic_h/22803.jpg",
"https://wallpapershome.com/images/pages/pic_h/22784.jpg",
"https://wallpapershome.com/images/pages/pic_h/22820.jpeg",
"https://wallpapershome.com/images/pages/pic_h/22836.jpg",
"https://wallpapershome.com/images/pages/pic_h/22830.jpg",
"https://wallpapershome.com/images/pages/pic_h/22833.jpg",
"https://wallpapershome.com/images/pages/pic_h/22793.jpeg",
"https://wallpapershome.com/images/pages/pic_h/22745.jpg",
"https://wallpapershome.com/images/pages/pic_h/22805.jpg",
"https://wallpapershome.com/images/pages/pic_h/19241.png",
"https://wallpapershome.com/images/pages/pic_h/22861.jpg",
"https://wallpapershome.com/images/pages/pic_h/20445.jpg",
"https://wallpapershome.com/images/pages/pic_h/22797.jpg",
"https://wallpapershome.com/images/pages/pic_h/22957.jpg",
"https://wallpapershome.com/images/pages/pic_h/22944.jpeg",
"https://wallpapershome.com/images/pages/pic_h/22311.jpg",
"https://wallpapershome.com/images/pages/pic_h/23166.jpg",
"https://wallpapershome.com/images/pages/pic_h/23168.jpg",
"https://wallpapershome.com/images/pages/pic_h/21665.jpg",
"https://wallpapershome.com/images/pages/pic_h/23114.jpg",
"https://wallpapershome.com/images/pages/pic_h/23115.jpg",
"https://wallpapershome.com/images/pages/pic_h/23024.jpg",
"https://wallpapershome.com/images/pages/pic_h/23053.jpg",
"https://wallpapershome.com/images/pages/pic_h/23019.jpg",
"https://wallpapershome.com/images/pages/pic_h/23017.jpg",
"https://wallpapershome.com/images/pages/pic_h/22998.jpg",
"https://wallpapershome.com/images/pages/pic_h/22999.jpg",
"https://wallpapershome.com/images/pages/pic_h/23033.jpg",
"https://wallpapershome.com/images/pages/pic_h/23034.jpg",
"https://wallpapershome.com/images/pages/pic_h/23035.jpg",
"https://wallpapershome.com/images/pages/pic_h/23022.jpg",
"https://wallpapershome.com/images/pages/pic_h/23023.jpg",
"https://wallpapershome.com/images/pages/pic_h/23025.jpg",
"https://wallpapershome.com/images/pages/pic_h/23026.jpg",
"https://wallpapershome.com/images/pages/pic_h/23018.jpg"
)
imageAdapter.addList(imageList)
}
}
Test 1: 그냥 기본 호출
아무처리도 하지않고 고화질 이미지를 그냥 호출했을때 메모리 사용량을 관찰했다. 코드는 아래와 같다. 실행 전마다 캐시를 비워주었다.
val imageUrl = getItemAt(position)
// Glide
Glide.with(itemView).load(imageUrl).into(imageView)
// Picasso
Picasso.get().load(imageUrl).into(imageView)
// Coil
imageView.load(imageUrl)
Test 1 - Glide
모든 이미지를 로딩하고 아래에서 위까지 스크롤 2번 한 후에 안정된 상태의 메모리 상태다. 아주잠깐 300MB까지 치솟다가 잠잠해진 후 GC가 자주 일어나지는 않았다.
Test 1 - Picasso
처음에 메모리를 적게 사용하나 싶더니 거의 500MB 넘게 찍고 가비지 컬렉팅을 엄청나게 하면서 메모리 사용량이 줄어갔다. Glide랑 별 차이없을거라 생각했는데 되게 달라서 신기했다. 최종적으로는 Glide보다 메모리 점유율이 높음...
Test 1 - Coli
읭? 다 된거 맞나? 싶을정도로 메모리 사용량이 적었던 Coil. 자세히 보니 그래픽에 사용된 메모리는 Glide 111MB에 비하면 엄청나게 차이자 많은 편은아닌데, Native 부분에서 50MB나 차이가 있다. 메모리 사용량이 제일 높을때도 100MB대를 유지 했다. 코루틴 사용해서 가볍다고 그렇게 말하고다니더니, 진짜였다!
*Native: C 나 C++ 코드에서 할당된 객체에 의한 메모리 사용량. 내가 쓴 코드에서 C/C++을 직접 사용하지 않아도, 안드로이드 프레임워크에서 사용함. 참조 (developer.android.com/studio/profile/memory-profiler.html#how-counted) |
Test 2: 사이즈 맞춰서 + CenterInside 호출
리사이징을 잘하는데 실력을 발휘 못했던 라이브러리가 있을까봐 2차전은 리사이징 기능을 넣어봤다. 테스트 결과는 아래 사진과 같다.
val imageUrl = getItemAt(position)
// Glide
Glide.with(itemView).load(imageUrl).override(400).centerInside().into(imageView)
// Picasso
Picasso.get().load(imageUrl).resize(400, 300).centerInside().into(imageView)
// Coil
imageView.load(imageUrl) {
size(400)
CenterInside()
}
'프로그래밍 > Android' 카테고리의 다른 글
[안드로이드] RecyclerView의 자동 스크롤 막기 (0) | 2021.01.08 |
---|---|
[안드로이드] Keytool을 이용해 KeyHash, SHA-1 얻기 (0) | 2021.01.07 |
잘 정리된 코틀린 코루틴 (0) | 2020.12.23 |
[안드로이드] 예제로 알아보는 Foreground Service (0) | 2020.10.15 |
[안드로이드] 서비스(Service)에 대해 알아보자 (0) | 2020.10.13 |