Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ViewPager in RecyclerView 성능 개선을 위해 코루틴 적용 #114

Merged
merged 3 commits into from
Nov 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,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
Expand All @@ -21,11 +20,17 @@ 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<CalendarDate, MonthAdapter.Holder>(diffUtil) {
class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : RecyclerView.Adapter<MonthAdapter.Holder>() {

private val schedules = mutableListOf<CalendarScheduleObject>()

private val currentList = mutableListOf<CalendarDate>()

private lateinit var calendarDesign: CalendarDesignObject

var selectedPosition = -1
Expand Down Expand Up @@ -54,7 +59,9 @@ 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)
notifyDataSetChanged()
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
Expand All @@ -67,6 +74,9 @@ class MonthAdapter(val onDaySelectStateListener: OnDaySelectStateListener) : Lis
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) {

Expand Down Expand Up @@ -100,14 +110,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.Default).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)
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -9,6 +10,7 @@ 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

Expand Down Expand Up @@ -87,63 +89,66 @@ class MonthPageAdapter : RecyclerView.Adapter<MonthPageAdapter.Holder>() {
onDayClick: OnDayClickListener?,
onDaySecondClick: OnDaySecondClickListener?
) {
val dates = mutableListOf<CalendarDate>()
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.Default).launch {
val dates = mutableListOf<CalendarDate>()
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
}

private fun makeDates(date: LocalDate, month: Int): List<CalendarDate> {
Expand Down