From bc2b169bfee739bd975ed16ad7cb3681ffc557a8 Mon Sep 17 00:00:00 2001 From: PsPLoG Date: Thu, 11 Nov 2021 01:32:15 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Issue=20#104=20feat:=20ViewPager=20in=20Rec?= =?UTF-8?q?yclerView=20=EC=84=B1=EB=8A=A5=20=EA=B0=9C=EC=84=A0=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=B4=20=EC=BD=94=EB=A3=A8=ED=8B=B4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9,=20ListAdapter=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GridLayoutManager가 diffUtils를 사용할 때 역순으로 binding되는 문제 때문에 ListAdapter 제거 - 달력 생성 및 binding할 때 UI delay를 줄이기 위해 코루틴 적용 (임시 해결책 근본적인 해결이 필요) --- .../ckscalendar/month/MonthAdapter.kt | 40 +++++-- .../ckscalendar/month/MonthPageAdapter.kt | 109 ++++++++++-------- 2 files changed, 91 insertions(+), 58 deletions(-) diff --git a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt index 8ab5df7b..380fd98e 100644 --- a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt +++ b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt @@ -2,6 +2,7 @@ package com.drunkenboys.ckscalendar.month import android.graphics.Color import android.text.TextUtils +import android.util.Log import android.util.TypedValue import android.view.Gravity import android.view.LayoutInflater @@ -9,7 +10,6 @@ import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.drunkenboys.ckscalendar.data.CalendarDate import com.drunkenboys.ckscalendar.data.CalendarDesignObject @@ -21,11 +21,19 @@ import com.drunkenboys.ckscalendar.listener.OnDaySecondClickListener import com.drunkenboys.ckscalendar.utils.context import com.drunkenboys.ckscalendar.utils.dp2px import com.drunkenboys.ckscalendar.utils.tintStroke +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext -class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : ListAdapter(diffUtil) { +class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : RecyclerView.Adapter() { + + private var timeTest = 0L private val schedules = mutableListOf() + private val currentList = mutableListOf() + private lateinit var calendarDesign: CalendarDesignObject var selectedPosition = -1 @@ -54,7 +62,11 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Lis this.currentPagePosition = currentPagePosition this.schedules.clear() this.schedules.addAll(schedules) - submitList(list) + this.currentList.clear() + this.currentList.addAll(list) + timeTest = System.currentTimeMillis() + Log.e(this::class.simpleName, "setItems") + notifyDataSetChanged() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder { @@ -100,14 +112,18 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Lis } binding.tvMonthDay.setTextColor(textColor) - binding.layoutMonthSchedule.removeAllViews() - val scheduleContainer = makePaddingScheduleList(item, schedules) - val hasAnySchedule = scheduleContainer.any { it != null } - if (hasAnySchedule) { - scheduleContainer.map { it ?: makeDefaultScheduleTextView() } - .forEach { - binding.layoutMonthSchedule.addView(it) + CoroutineScope(Dispatchers.IO).launch { + val scheduleContainer = makePaddingScheduleList(item, schedules) + val hasAnySchedule = scheduleContainer.any { it != null } + if (hasAnySchedule) { + withContext(Dispatchers.Main) { + binding.layoutMonthSchedule.removeAllViews() + scheduleContainer.map { it ?: makeDefaultScheduleTextView() } + .forEach { + binding.layoutMonthSchedule.addView(it) + } } + } } } @@ -207,4 +223,8 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Lis private const val MAX_VISIBLE_SCHEDULE_SIZE = 3 } + + override fun getItemCount(): Int { + return currentList.size + } } diff --git a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt index deaeccef..fba1943e 100644 --- a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt +++ b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt @@ -1,5 +1,6 @@ package com.drunkenboys.ckscalendar.month +import android.util.Log import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.GridLayoutManager @@ -9,12 +10,15 @@ import com.drunkenboys.ckscalendar.databinding.ItemMonthPageBinding import com.drunkenboys.ckscalendar.listener.OnDayClickListener import com.drunkenboys.ckscalendar.listener.OnDaySecondClickListener import com.drunkenboys.ckscalendar.utils.TimeUtils.parseDayWeekToDayType +import kotlinx.coroutines.* import java.time.DayOfWeek import java.time.LocalDate class MonthPageAdapter : RecyclerView.Adapter() { + private var timeTest = 0L + private val list = mutableListOf() private val schedules = mutableListOf() @@ -36,6 +40,9 @@ class MonthPageAdapter : RecyclerView.Adapter() { cachedCalendar.clear() this.list.clear() this.list.addAll(list) + + timeTest = System.currentTimeMillis() + Log.e(this::class.simpleName, "setItems") notifyDataSetChanged() } @@ -87,63 +94,69 @@ class MonthPageAdapter : RecyclerView.Adapter() { onDayClick: OnDayClickListener?, onDaySecondClick: OnDaySecondClickListener? ) { - val dates = mutableListOf() - val startMonth = item.startDate.monthValue - val startDay = item.startDate.dayOfWeek - val endMonth = item.endDate.monthValue - - cachedCalendar[item.id]?.let { - dates.addAll(it) - } ?: run { - (startMonth..endMonth).forEach { month -> - when (month) { - startMonth -> { - // add Start Padding - if (startDay != DayOfWeek.SUNDAY) { - dates.addAll(makePadding(startDay.ordinal)) + CoroutineScope(Dispatchers.IO).launch { + val dates = mutableListOf() + val startMonth = item.startDate.monthValue + val startDay = item.startDate.dayOfWeek + val endMonth = item.endDate.monthValue + + cachedCalendar[item.id]?.let { + dates.addAll(it) + } ?: run { + (startMonth..endMonth).forEach { month -> + when (month) { + startMonth -> { + // add Start Padding + if (startDay != DayOfWeek.SUNDAY) { + dates.addAll(makePadding(startDay.ordinal)) + } + + // add Start Dates + dates.addAll(makeDates(item.startDate, month)) + } + else -> { + // add Normal Dates + dates.addAll(makeDates(item.endDate, month)) } - - // add Start Dates - dates.addAll(makeDates(item.startDate, month)) - } - else -> { - // add Normal Dates - dates.addAll(makeDates(item.endDate, month)) } } + // add End Padding + val weekPadding = 6 - dates.size % weekSize + dates.addAll(makePadding(weekPadding)) + + // add FullSize Padding + if (dates.size < calendarFullSize) { + val fullSizePadding = calendarFullSize - dates.size - 1 + dates.addAll(makePadding(fullSizePadding)) + } } - // add End Padding - val weekPadding = 6 - dates.size % weekSize - dates.addAll(makePadding(weekPadding)) - - // add FullSize Padding - if (dates.size < calendarFullSize) { - val fullSizePadding = calendarFullSize - dates.size - 1 - dates.addAll(makePadding(fullSizePadding)) - } - } - // check and set recycle data - if (lastSelectPagePosition == adapterPosition) { - monthAdapter.selectedPosition = lastSelectDayPosition - } else { - monthAdapter.selectedPosition = -1 - } + // check and set recycle data + if (lastSelectPagePosition == adapterPosition) { + monthAdapter.selectedPosition = lastSelectDayPosition + } else { + monthAdapter.selectedPosition = -1 + } - if (isFirstToday) { - dates.find { - it.date.monthValue == today.monthValue && - it.date.dayOfMonth == today.dayOfMonth && - it.dayType != DayType.PADDING - }?.let { - it.isSelected = true - isFirstToday = false + if (isFirstToday) { + dates.find { + it.date.monthValue == today.monthValue && + it.date.dayOfMonth == today.dayOfMonth && + it.dayType != DayType.PADDING + }?.let { + it.isSelected = true + isFirstToday = false + } + } + withContext(Dispatchers.Main){ + monthAdapter.setItems(dates, schedules, calendarDesign, adapterPosition) + monthAdapter.onDateClickListener = onDayClick + monthAdapter.onDateSecondClickListener = onDaySecondClick } } - monthAdapter.setItems(dates, schedules, calendarDesign, adapterPosition) - monthAdapter.onDateClickListener = onDayClick - monthAdapter.onDateSecondClickListener = onDaySecondClick + + Log.e("monthPage", "bind end $adapterPosition ${System.currentTimeMillis() - timeTest}") } private fun makeDates(date: LocalDate, month: Int): List { From ffd22b21d82e5d20e60d24b08ebf52f865eda6cb Mon Sep 17 00:00:00 2001 From: PsPLoG Date: Thu, 11 Nov 2021 10:37:00 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Issue=20#104=20feat:=20=EC=BD=94=EB=A3=A8?= =?UTF-8?q?=ED=8B=B4=20Dispatcher=20=EB=B3=80=EA=B2=BD=20IO=20->=20Default?= =?UTF-8?q?,=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/drunkenboys/ckscalendar/month/MonthAdapter.kt | 6 +----- .../drunkenboys/ckscalendar/month/MonthPageAdapter.kt | 10 +--------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt index 380fd98e..c8bcc7f4 100644 --- a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt +++ b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt @@ -28,8 +28,6 @@ import kotlinx.coroutines.withContext class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : RecyclerView.Adapter() { - private var timeTest = 0L - private val schedules = mutableListOf() private val currentList = mutableListOf() @@ -64,8 +62,6 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Rec this.schedules.addAll(schedules) this.currentList.clear() this.currentList.addAll(list) - timeTest = System.currentTimeMillis() - Log.e(this::class.simpleName, "setItems") notifyDataSetChanged() } @@ -112,7 +108,7 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Rec } binding.tvMonthDay.setTextColor(textColor) - CoroutineScope(Dispatchers.IO).launch { + CoroutineScope(Dispatchers.Default).launch { val scheduleContainer = makePaddingScheduleList(item, schedules) val hasAnySchedule = scheduleContainer.any { it != null } if (hasAnySchedule) { diff --git a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt index fba1943e..48fac801 100644 --- a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt +++ b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthPageAdapter.kt @@ -17,8 +17,6 @@ import java.time.LocalDate class MonthPageAdapter : RecyclerView.Adapter() { - private var timeTest = 0L - private val list = mutableListOf() private val schedules = mutableListOf() @@ -40,9 +38,6 @@ class MonthPageAdapter : RecyclerView.Adapter() { cachedCalendar.clear() this.list.clear() this.list.addAll(list) - - timeTest = System.currentTimeMillis() - Log.e(this::class.simpleName, "setItems") notifyDataSetChanged() } @@ -94,7 +89,7 @@ class MonthPageAdapter : RecyclerView.Adapter() { onDayClick: OnDayClickListener?, onDaySecondClick: OnDaySecondClickListener? ) { - CoroutineScope(Dispatchers.IO).launch { + CoroutineScope(Dispatchers.Default).launch { val dates = mutableListOf() val startMonth = item.startDate.monthValue val startDay = item.startDate.dayOfWeek @@ -154,9 +149,6 @@ class MonthPageAdapter : RecyclerView.Adapter() { monthAdapter.onDateSecondClickListener = onDaySecondClick } } - - - Log.e("monthPage", "bind end $adapterPosition ${System.currentTimeMillis() - timeTest}") } private fun makeDates(date: LocalDate, month: Int): List { From ace61c49c5b1f4bc3dab60512a58620e5a619705 Mon Sep 17 00:00:00 2001 From: PsPLoG Date: Thu, 11 Nov 2021 10:57:17 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Issue=20#104=20refactor:=20getItemCount=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/drunkenboys/ckscalendar/month/MonthAdapter.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt index c8bcc7f4..24fe8a80 100644 --- a/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt +++ b/library/src/main/java/com/drunkenboys/ckscalendar/month/MonthAdapter.kt @@ -2,7 +2,6 @@ package com.drunkenboys.ckscalendar.month import android.graphics.Color import android.text.TextUtils -import android.util.Log import android.util.TypedValue import android.view.Gravity import android.view.LayoutInflater @@ -75,6 +74,9 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Rec holder.bind(currentList[position]) } + override fun getItemCount(): Int = currentList.size + + inner class Holder(private val binding: ItemMonthCellBinding, private val calculateHeight: Int) : RecyclerView.ViewHolder(binding.root) { @@ -219,8 +221,4 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Rec private const val MAX_VISIBLE_SCHEDULE_SIZE = 3 } - - override fun getItemCount(): Int { - return currentList.size - } }