Glide preload 적용

순순·2024년 12월 2일

Android

목록 보기
11/12

문제 배경

고화질 사진을 많이 띄워야 하는 프로젝트가 있었다. Glide 는 한번 로딩했던 사진을 알아서 캐싱 처리해주는 좋은 라이브러리지만, 최초 진입시엔 캐싱처리가 되지 않은 상태이기 때문에 로딩이 느릴 수밖에 없었다.

그러다보니 서버단이 아닌 앱단에서 조금이라도 로딩 속도를 개선해 사용자 경험을 개선할 수 있는 방법이 있으면 좋겠다고 생각했다.

해결 방법

다행히 구글링 해보니 Glide 자체 기능에 preload 라는게 있었다. 간단하게 설명하자면 recyclerView가 스크롤 되기 전에 사진을 미리 로드하는건데, 적용은 해당 블로그를 참고했다.


적용 코드

Glide 로 이미지 로드하는 코드는 여러 파일에서 사용하기에 확장 함수로 만들어줬다. 원래는 아래 setImage 함수를 사용해서 띄우고 있었고, 이번에 preload 함수를 추가해줬다.

package com.example.presentation.util.ext

import android.content.Context
import android.widget.ImageView
import com.bumptech.glide.Glide

fun ImageView.setImage(imageView: ImageView, url: String?) {
    Glide.with(this).load(url)
        .into(imageView)
}

fun Context.preloadImage(url: String?) {
    if (url.isNullOrEmpty()) return
    Glide.with(this)
        .load(url)
        .preload()
}

recyclerView 의 어댑터에서 호출
recyclerView는 화면에 보이는 아이템만 그리기 때문에, 스크롤 중에 곧 화면에 나타날 아이템의 이미지를 미리 로드해 조금 빠르게 띄우는 것. 이 과정에서 인덱스를 기반으로 현재 아이템 주변의 이미지 URL을 가져와야 하므로, position 값이 필요하다.


class ResultViewAdapter(
    private val onClickStudio: (String, String) -> Unit
) : ListAdapter<StudioInfoWithConcept, ResultViewHolder>(StudioDiffCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ResultViewHolder {
        return ResultViewHolder(
            ItemResultViewBinding.inflate(LayoutInflater.from(parent.context), parent, false),
            onClickStudio
        )
    }

    override fun onBindViewHolder(holder: ResultViewHolder, position: Int) {
        val studio = getItem(position)
        val context: Context = holder.itemView.context

        setImagePreload(context, position)
        holder.bind(studio)
    }

    override fun getItemCount(): Int {
        return currentList.size
    }

    companion object {
        private val StudioDiffCallback = object : DiffUtil.ItemCallback<StudioInfoWithConcept>() {
            override fun areItemsTheSame(
                oldItem: StudioInfoWithConcept,
                newItem: StudioInfoWithConcept
            ): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(
                oldItem: StudioInfoWithConcept,
                newItem: StudioInfoWithConcept
            ): Boolean {
                return oldItem == newItem
            }
        }
    }

	// 현재 인덱스 기준으로 preload
    private fun setImagePreload(context: Context, position: Int) {
        if (position < currentList.size - 1) {
            context.preloadImage(currentList[position + 1].profileURL)
        }
        if (position > 0) {
            context.preloadImage(currentList[position - 1].profileURL)
        }
    }
}

preload 유무 차이를 비교하기 위해 캐시 삭제 및 에뮬레이터 wipe data 하고 재시도해봤다. 확실히 기존보다 조금 더 빠르게 띄워졌다!

한번 이미지를 띄운 이후에는 글라이드가 알아서 캐시처리를 해주기 때문에 사진이 빨리 띄워지지만, 초기 로딩속도를 조금이나마 개선하는 것이 목적이라면 이렇게 preload 를 적용하는게 좋을 것 같다.

적용 전

적용 후


해당 경험을 통해 알게된 점

잘 활용하지 않았던 기능을 적용해 새로운 최적화를 시도해보는 것은 값진 경험이었다. 라이브러리를 너무 관성적으로 사용하지 않았나- 하는 생각이 들어 반성하는 계기가 되었다.


참고로 Glide 에는 preload 외에도 여러 기능이 있었다.
Glide.with(this)
    .load(R.drawable.imgfile)
    .placeholder(R.drawable.img_place_holder)
    .error(R.drawable.img_error)
    .fallback(R.drawable.no_img)
    .into(imageView)
  • placeholder() : 이미지 로드가 되기 전에 나타날 이미지를 설정할 수 있다.
  • error() : 이미지 리소스를 불러오다가 에러가 발생했을 경우의 이미지를 설정할 수 있다.
  • fallback() : 로드할 이미지 리소스가 null인 경우 보여줄 이미지를 설정할 수 있다.
profile
플러터와 안드로이드를 공부합니다

0개의 댓글