StwParser.kt now collects all its data before adding everything to the database all at once, fixing problems where LiveData would update before all transactions were finished; ViewPagers have been updated to use Adapters extending FragmentStateAdapter instead of RecyclerView.Adapter

This commit is contained in:
denizk0461
2023-04-27 21:58:10 +02:00
parent ccd77a5daf
commit ce7b854e8c
15 changed files with 373 additions and 164 deletions
@@ -49,6 +49,15 @@ class CanteenOfferItemAdapter(
// Retrieve item for current position
val currentItem = offers[position]
/*
* Children of the line container MUST be removed before any are added, as otherwise, during
* recycling, lines will be duplicated when they are scrolled off the visible screen area
* and then scrolled onto the screen again. In other terms, if removeAllViews() wasn't
* called and the user was to scroll down a list and then back up again, the items at the
* top of the list would be added again, creating duplicates.
*/
holder.binding.lineContainer.removeAllViews()
// If an item has been added to mark that there are no offers available, tell the user
if (currentItem.category == "NO\$ITEMS") {
@@ -1,16 +1,15 @@
package com.denizk0461.studip.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.denizk0461.studip.databinding.ItemScrollablePageBinding
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.denizk0461.studip.fragment.CanteenPageFragment
import com.denizk0461.studip.model.CanteenOfferGroup
/**
* Custom RecyclerView adapter for managing multiple pages of canteen offers in a RecyclerView or
* ViewPager.
* Custom ViewPager adapter for managing multiple pages of canteen offers.
*
* @param fragmentActivity parent fragment activity
* @param offers all offers for a given canteen, grouped by category (not filtered by day at
* this point)
* @param daysCovered tells for how many days offers are available for.
@@ -20,54 +19,23 @@ import com.denizk0461.studip.model.CanteenOfferGroup
* @param displayAllergens whether the user wants allergens to be marked
*/
class CanteenOfferPageAdapter(
fragmentActivity: FragmentActivity,
private var offers: List<CanteenOfferGroup>,
private var daysCovered: Int,
private val onClickListener: CanteenOfferItemAdapter.OnClickListener,
private val displayAllergens: Boolean,
) : RecyclerView.Adapter<CanteenOfferPageAdapter.CanteenOfferPageViewHolder>() {
/**
* View holder class for parent class
*
* @param binding view binding object
*/
class CanteenOfferPageViewHolder(val binding: ItemScrollablePageBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CanteenOfferPageViewHolder =
CanteenOfferPageViewHolder(
ItemScrollablePageBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
) : FragmentStateAdapter(fragmentActivity) {
// Returns the count of days covered
override fun getItemCount(): Int = daysCovered
override fun onBindViewHolder(holder: CanteenOfferPageViewHolder, position: Int) {
holder.binding.pageRecyclerView.apply {
// Set page to horizontally scroll
layoutManager = LinearLayoutManager(
holder.binding.root.context, LinearLayoutManager.VERTICAL, false
)
/*
* Create new adapter for every page. Attribute position denotes day that will be set up
* by the newly created adapter (0 = Monday, 4 = Friday)
* TODO check if the filtered list is empty, and tell the user if it is
*/
adapter = CanteenOfferItemAdapter(
offers.filter { it.dateId == position },
onClickListener,
displayAllergens,
)
// Animate creation of new page
scheduleLayoutAnimation()
}
}
override fun createFragment(position: Int): Fragment =
CanteenPageFragment(
offers,
onClickListener,
displayAllergens,
position,
)
/**
* Update the entire list of items
@@ -1,61 +1,31 @@
package com.denizk0461.studip.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.databinding.ItemScrollablePageBinding
import com.denizk0461.studip.fragment.EventPageFragment
/**
* Custom RecyclerView adapter for managing multiple pages of Stud.IP events in a RecyclerView or
* ViewPager.
* Custom ViewPager adapter for managing multiple pages of Stud.IP events.
*
* @param fragmentActivity parent fragment activity
* @param events all events (not filtered by day at this point)
* @param onClickListener for managing click and long press events
*/
class StudIPEventPageAdapter(
fragmentActivity: FragmentActivity,
private var events: List<StudIPEvent>,
private val onClickListener: StudIPEventItemAdapter.OnClickListener,
) : RecyclerView.Adapter<StudIPEventPageAdapter.EventPageViewHolder>() {
/**
* View holder class for parent class
*
* @param binding view binding object
*/
class EventPageViewHolder(val binding: ItemScrollablePageBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventPageViewHolder = EventPageViewHolder(
ItemScrollablePageBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
) : FragmentStateAdapter(fragmentActivity) {
/*
* Assume that there will always be 5 pages, for 5 days - Monday through Friday.
* TODO is it right to assume that the user only has events on weekdays?
* Assume that there will always be 7 pages, for 7 days - Monday through Sunday.
*/
override fun getItemCount(): Int = 5
override fun getItemCount(): Int = 7
// Set up page
override fun onBindViewHolder(holder: EventPageViewHolder, position: Int) {
holder.binding.pageRecyclerView.apply {
// Set page to horizontally scroll
layoutManager = LinearLayoutManager(holder.binding.root.context, LinearLayoutManager.VERTICAL, false)
/*
* Create new adapter for every page. Attribute position denotes day that will be set up
* by the newly created adapter (0 = Monday, 4 = Friday)
*/
adapter = StudIPEventItemAdapter(events, currentDay = position, onClickListener) // TODO check if empty
// Animate creation of new page
scheduleLayoutAnimation()
}
}
override fun createFragment(position: Int): Fragment =
EventPageFragment(events, position, onClickListener)
/**
* Update the entire list of items