[Kotlin] RecyclerView에서 데이터 변화 시 이미지 깜박임 제거

park_sujeong·2022년 11월 9일
0

Android

목록 보기
7/13
post-thumbnail

RecyclerView를 사용할 때 데이터가 변하면 그것을 adapter에 반영해줘야한다. 그 과정에서 RecyclerView의 아이템 자체가 깜박거리는 것은 animator를 false로 설정하면 되지만 Glide로 로드한 이미지는 여전히 깜박거린다.

아래 그것에 대해 내가 찾은 방법을 적는다.




RecyclerView 아이템 깜박임 제거

우선 RecyclerView의 아이템 자체가 깜박거리는 것은 RecyclerView에 아래 코드를 추가하면 된다. 애니메이션을 끄는 코드다.

recyclerView.apply {
		...
        itemAnimator = null
}




Glide 이미지 깜박임 제거

RecyclerView 아이템의 이미지에 Glide로 로드했다. 그리고 diffUtil이나 NotifyDataSetChanged()등으로 데이터가 변경되면 adapter에 변경사항을 알리고 adapter는 변경 내용을 반영한다.

아래 이미지에서는 이미지나 제목의 변화는 없지만 클릭 시 가지고 있는 데이터의 isPlaying이라는 필드에서 변화가 생겨서 그것을 adapter가 반영해준다. 그리고 반영 때 image가 Glide를 통해 다시 로드되며 깜박이는 것을 볼 수 있다.

심히 거슬린다.



아래 코드는 솔루션 적용 전 코드다.
ViewHolder 클래스 내의 함수 bind를 통해 각 아이템에 맞는 제목과 이미지를 넣는다.
Glide를 통해 이미지를 로드하고 있다.

inner class ViewHolder(view: View): RecyclerView.ViewHolder(view) {

  fun bind(sound: Sound) {
      val trackTextView =itemView.findViewById<TextView>(R.id.item_track_text_view)
      val categoryTextView =itemView.findViewById<TextView>(R.id.item_category_text_view)
      val coverImageView =itemView.findViewById<ImageView>(R.id.item_cover_image_view)

      trackTextView.text = "제목 "
      categoryTextView.text = "부제목 "

      Glide.with(context)
          .load(sound.imgUrl)
          .override(100, 100)
          .skipMemoryCache(true)
          .dontAnimate()
          .into(coverImageView)

  }

}



이미지 깜박거림 제거를 위해서는 Glide 옵션에 thumnail을 추가하는 것이다.

Glide.with(context)
  .load(sound.imgUrl)
  .thumbnail(Glide.with(context).load(sound.imgUrl).override(100, 100))
  .override(100, 100)
  .skipMemoryCache(true)
  .dontAnimate()
  .into(coverImageView)



코드를 적용하고 나면 아래처럼 깜박거림이 사라진다.




또 다른 방법

나는 사용하지 않았지만, Adapter 클래스 내에서 getItemViewType(), getItemId()를 오버라이딩받아서 아이템마다 아이디를 부여하는 방법도 있다.

Adapter

class PlayListAdapter(
  private val context: Context
  ) : RecyclerView.Adapter<PlayListAdapter.ViewHolder>()  {

  inner class ViewHolder(view: View): RecyclerView.ViewHolder(view) {

      fun bind(sound: Sound) {
          val trackTextView =itemView.findViewById<TextView>(R.id.item_track_text_view)
          val categoryTextView =itemView.findViewById<TextView>(R.id.item_category_text_view)
          val coverImageView =itemView.findViewById<ImageView>(R.id.item_cover_image_view)

           trackTextView.text = "제목"
           categoryTextView.text = "부제목"

          Glide.with(context)
              .asBitmap()
              .load(sound.imgUrl)
              .override(100, 100)
              .skipMemoryCache(true)
              .dontAnimate()
              .into(object : CustomTarget<Bitmap>() {
                  override fun onResourceReady(
                      resource: Bitmap,
                      transition: Transition<in Bitmap>?
                  ) {
                      coverImageView.setImageBitmap(resource)
                  }

                  override fun onLoadCleared(placeholder: Drawable?) {
                  }

              })

      }

  }

...

  override fun getItemViewType(position: Int): Int {
      return position
  }

  override fun getItemId(position: Int): Long {
      return position.toLong()
  }

}



adapter를 초기화할때 초기화 후 꼭 setHasStableIds(true)를 넣어줘야한다. RecyclerView에 adapter를 붙이고 나서 setHasStableIds()를 선언하면 에러나니까 붙이기 전에 넣어준다.

Activity

val playListAdapter = PlayListAdapter(requireContext())
playListAdapter.setHasStableIds(true)





마치며...

getViewType()을 사용하면 RecyclerView를 drag&drop할때 이상하게 되는 현상이 발생한다. 이 부분은 나중에 한번 알아봐야겠다.

profile
Android Developer

0개의 댓글