From cfd1a2f2b8717a46b075b868c64a6d3dd66df4c9 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Fri, 2 Apr 2021 22:22:36 +0100 Subject: [PATCH] Second attempt for correct passes AsyncListDiffer --- .../look4sat/ui/passesScreen/PassesAdapter.kt | 75 ++++++++++--------- .../ui/passesScreen/PassesFragment.kt | 7 +- .../look4sat/ui/polarScreen/PolarViewModel.kt | 4 +- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt index 411c6d7d..1ab7f7a3 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt @@ -21,6 +21,8 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.os.bundleOf import androidx.navigation.findNavController +import androidx.recyclerview.widget.AsyncListDiffer +import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.rtbishop.look4sat.R import com.rtbishop.look4sat.data.model.SatPass @@ -30,46 +32,48 @@ import com.rtbishop.look4sat.utility.navigateSafe import java.text.SimpleDateFormat import java.util.* -class PassesAdapter(private val shouldUseUTC: Boolean = false) : - RecyclerView.Adapter() { +class PassesAdapter(private val isUTC: Boolean) : RecyclerView.Adapter() { - private var satPassList: MutableList = mutableListOf() + private val diffCallback = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: SatPass, newItem: SatPass): Boolean { + return oldItem.catNum == newItem.catNum && oldItem.startDate == newItem.startDate + } - fun setList(list: MutableList) { - satPassList = list - notifyDataSetChanged() + override fun areContentsTheSame(oldItem: SatPass, newItem: SatPass): Boolean { + return oldItem.progress == newItem.progress + } + } + private val differ = AsyncListDiffer(this, diffCallback) + private var allPasses = emptyList() + private var currentPasses = emptyList() + + fun submitList(passes: List) { + allPasses = passes.map { it.copy() } + currentPasses = passes.map { it.copy() } + tickDiffer(System.currentTimeMillis()) } - fun tickPasses(timeNow: Long) { - val iterator = satPassList.listIterator() - while (iterator.hasNext()) { - val satPass = iterator.next() - if (!satPass.isDeepSpace) { - if (satPass.progress < 100) { - val timeStart = satPass.startDate.time - if (timeNow > timeStart) { - val timeEnd = satPass.endDate.time - val index = satPassList.indexOf(satPass) - val deltaNow = timeNow.minus(timeStart).toFloat() - val deltaTotal = timeEnd.minus(timeStart).toFloat() - satPass.progress = ((deltaNow / deltaTotal) * 100).toInt() - notifyItemChanged(index) - } - } else { - val index = satPassList.indexOf(satPass) - iterator.remove() - notifyItemRemoved(index) + fun tickDiffer(timeNow: Long) { + val list = currentPasses.map { it.copy() } + list.forEach { pass -> + if (!pass.isDeepSpace) { + val timeStart = pass.startDate.time + if (timeNow > timeStart) { + val timeEnd = pass.endDate.time + val deltaNow = timeNow.minus(timeStart).toFloat() + val deltaTotal = timeEnd.minus(timeStart).toFloat() + pass.progress = ((deltaNow / deltaTotal) * 100).toInt() } } } + currentPasses = list.filter { pass -> pass.progress < 100 } + differ.submitList(currentPasses) } - override fun getItemCount(): Int { - return satPassList.size - } + override fun getItemCount() = differ.currentList.size override fun getItemViewType(position: Int): Int { - return if (satPassList[position].isDeepSpace) 1 + return if (differ.currentList[position].isDeepSpace) 1 else 0 } @@ -82,10 +86,11 @@ class PassesAdapter(private val shouldUseUTC: Boolean = false) : } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + val pass = differ.currentList[position] if (holder.itemViewType == 0) { - (holder as SatPassLeoHolder).bind(satPassList[position], position, shouldUseUTC) + (holder as SatPassLeoHolder).bind(pass, differ.currentList.indexOf(pass), isUTC) } else { - (holder as SatPassGeoHolder).bind(satPassList[position], position) + (holder as SatPassGeoHolder).bind(pass, differ.currentList.indexOf(pass)) } } @@ -103,7 +108,7 @@ class PassesAdapter(private val shouldUseUTC: Boolean = false) : private val startFormat = SimpleDateFormat(startTimeFormat, Locale.getDefault()) private val endFormat = SimpleDateFormat(endTimeFormat, Locale.getDefault()) - fun bind(satPass: SatPass, position: Int, shouldUseUTC: Boolean) { + fun bind(satPass: SatPass, passIndex: Int, shouldUseUTC: Boolean) { binding.apply { if (shouldUseUTC) { startFormat.timeZone = timeZoneUTC @@ -122,7 +127,7 @@ class PassesAdapter(private val shouldUseUTC: Boolean = false) : itemView.setOnClickListener { if (satPass.progress < 100) { - val bundle = bundleOf("index" to position) + val bundle = bundleOf("index" to passIndex) itemView.findNavController().navigateSafe(R.id.action_passes_to_polar, bundle) } } @@ -144,7 +149,7 @@ class PassesAdapter(private val shouldUseUTC: Boolean = false) : private val altFormat = itemView.context.getString(R.string.pat_altitude) private val elevFormat = itemView.context.getString(R.string.pat_elevation) - fun bind(satPass: SatPass, position: Int) { + fun bind(satPass: SatPass, passIndex: Int) { binding.apply { passGeoSatName.text = satPass.name passGeoSatId.text = String.format(satIdFormat, satPass.catNum) @@ -154,7 +159,7 @@ class PassesAdapter(private val shouldUseUTC: Boolean = false) : } itemView.setOnClickListener { - val bundle = bundleOf("index" to position) + val bundle = bundleOf("index" to passIndex) itemView.findNavController().navigateSafe(R.id.action_passes_to_polar, bundle) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt index 7aa5b945..510bce91 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt @@ -51,7 +51,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes) { adapter = passesAdapter isVerticalScrollBarEnabled = false layoutManager = LinearLayoutManager(context) - (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false +// (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false addItemDecoration(RecyclerDivider(R.drawable.rec_divider_dark)) } passesRefresh.setOnClickListener { viewModel.forceCalculation() } @@ -72,7 +72,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes) { when (result) { is Result.Success -> { passes = result.data.toMutableList() - passesAdapter.setList(passes) + passesAdapter.submitList(passes) binding.apply { passesError.visibility = View.INVISIBLE passesProgress.visibility = View.INVISIBLE @@ -115,7 +115,8 @@ class PassesFragment : Fragment(R.layout.fragment_passes) { val millisBeforeEnd = lastPass.endDate.time.minus(timeNow) binding.passesTimer.text = millisBeforeEnd.formatForTimer() } - passesAdapter.tickPasses(timeNow) +// passesAdapter.tickPasses(timeNow) + passesAdapter.tickDiffer(timeNow) } else { binding.passesTimer.text = 0L.formatForTimer() } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt index c5dff676..a6cda624 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt @@ -46,9 +46,7 @@ class PolarViewModel @Inject constructor( fun getPass(passId: Int) = liveData { passesRepo.passes.collect { passes -> - if (passes is Result.Success) { - emit(passes.data[passId]) - } + if (passes is Result.Success) emit(passes.data[passId]) } }