diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerAdapter.kt index f72f9e91..823c76f3 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerAdapter.kt @@ -1,5 +1,6 @@ package kr.co.vividnext.sodalive.v2.widget.banner +import android.annotation.SuppressLint import android.graphics.Outline import android.view.LayoutInflater import android.view.View @@ -38,19 +39,17 @@ class BannerAdapter( this.items.addAll(items) val newItemCount = itemCount when { - previousItemCount == 0 && newItemCount > 0 -> notifyItemRangeInserted(0, newItemCount) - previousItemCount > 0 && newItemCount == 0 -> notifyItemRangeRemoved(0, previousItemCount) - previousItemCount == newItemCount -> notifyItemRangeChanged(0, newItemCount) - else -> { - notifyItemRangeRemoved(0, previousItemCount) - notifyItemRangeInserted(0, newItemCount) - } + previousItemCount == 0 && newItemCount == 1 -> notifyItemInserted(0) + previousItemCount == 1 && newItemCount == 0 -> notifyItemRemoved(0) + previousItemCount == 1 && newItemCount == 1 -> notifyItemChanged(0) + else -> notifyVirtualItemsChanged() } } fun setItemSizePx(itemSizePx: Int) { + val shouldNotify = this.itemSizePx != itemSizePx this.itemSizePx = itemSizePx - notifyItemsChanged() + if (shouldNotify) notifyVisibleItemsChanged() } fun setOnClickItem(listener: ((BannerItem) -> Unit)?) { @@ -62,8 +61,9 @@ class BannerAdapter( } fun setPreviewImageResource(resId: Int) { + val shouldNotify = previewImageResId != resId previewImageResId = resId - notifyItemsChanged() + if (shouldNotify) notifyVisibleItemsChanged() } fun toRealIndex(position: Int): Int = if (items.isEmpty()) 0 else position % items.size @@ -106,9 +106,17 @@ class BannerAdapter( } } - private fun notifyItemsChanged() { - val count = itemCount - if (count > 0) notifyItemRangeChanged(0, count) + private fun notifyVisibleItemsChanged() { + when (itemCount) { + 0 -> Unit + 1 -> notifyItemChanged(0) + else -> notifyVirtualItemsChanged() + } + } + + @SuppressLint("NotifyDataSetChanged") + private fun notifyVirtualItemsChanged() { + notifyDataSetChanged() } private companion object { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerItem.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerItem.kt index 99547ed6..affeadbb 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerItem.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerItem.kt @@ -1,6 +1,11 @@ package kr.co.vividnext.sodalive.v2.widget.banner +import kr.co.vividnext.sodalive.settings.event.EventItem + data class BannerItem( - val bannerId: String?, - val imageUrl: String + val imageUrl: String, + val eventItem: EventItem?, + val creatorId: Long?, + val seriesId: Long?, + val link: String? ) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerView.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerView.kt index 6920f826..e11fd092 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerView.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerView.kt @@ -146,7 +146,13 @@ class BannerView @JvmOverloads constructor( if (previewImageResId != 0) adapter.setPreviewImageResource(previewImageResId) if (previewItemCount > 0) { items = List(previewItemCount) { index -> - BannerItem(bannerId = "preview-$index", imageUrl = "") + BannerItem( + imageUrl = "", + eventItem = null, + creatorId = null, + seriesId = null, + link = "preview-$index" + ) } currentIndex = BannerState.from(previewItemCount, previewCurrentIndex).currentIndex visibility = VISIBLE diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerViewTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerViewTest.kt index e5b176c7..352c81ec 100644 --- a/app/src/test/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerViewTest.kt +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerViewTest.kt @@ -67,6 +67,74 @@ class BannerViewTest { assertEquals(items[1], clickedItem) } + @Test + fun `adapter는 carousel 설정 시 max range notify를 호출하지 않는다`() { + val adapter = BannerAdapter() + var insertedItemCount = 0 + var changedItemCount = 0 + var dataSetChangedCount = 0 + adapter.registerAdapterDataObserver( + object : RecyclerView.AdapterDataObserver() { + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + insertedItemCount = itemCount + } + + override fun onItemRangeChanged(positionStart: Int, itemCount: Int) { + changedItemCount = itemCount + } + + override fun onChanged() { + dataSetChangedCount += 1 + } + } + ) + + adapter.submitItems(listOf(sampleItem("1"), sampleItem("2"))) + adapter.setItemSizePx(100) + + assertEquals(0, insertedItemCount) + assertEquals(0, changedItemCount) + assertEquals(2, dataSetChangedCount) + } + + @Test + fun `adapter는 단일 배너 설정 시 specific notify를 호출한다`() { + val adapter = BannerAdapter() + var insertedItemCount = 0 + var changedItemCount = 0 + var removedItemCount = 0 + var dataSetChangedCount = 0 + adapter.registerAdapterDataObserver( + object : RecyclerView.AdapterDataObserver() { + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + insertedItemCount += itemCount + } + + override fun onItemRangeChanged(positionStart: Int, itemCount: Int) { + changedItemCount += itemCount + } + + override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { + removedItemCount += itemCount + } + + override fun onChanged() { + dataSetChangedCount += 1 + } + } + ) + + adapter.submitItems(listOf(sampleItem("1"))) + adapter.setItemSizePx(100) + adapter.submitItems(listOf(sampleItem("2"))) + adapter.submitItems(emptyList()) + + assertEquals(1, insertedItemCount) + assertEquals(2, changedItemCount) + assertEquals(1, removedItemCount) + assertEquals(0, dataSetChangedCount) + } + @Test fun `배너 view는 빈 목록이면 숨기고 단일 목록이면 counter를 숨긴다`() { val view = inflateBannerView() @@ -533,8 +601,11 @@ class BannerViewTest { } private fun sampleItem(id: String) = BannerItem( - bannerId = id, - imageUrl = "https://example.com/banner-$id.png" + imageUrl = "https://example.com/banner-$id.png", + eventItem = null, + creatorId = id.toLongOrNull(), + seriesId = null, + link = "https://example.com/banner-$id" ) private fun exactly(size: Int): Int = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY)