Improve History Session Adapter

feature/top10
Aurelien Hubert 7 years ago
parent 36b1dddec4
commit 21802eb7ec
  1. 83
      app/src/main/java/net/pokeranalytics/android/ui/adapter/HistorySessionRowRepresentableAdapter.kt
  2. 80
      app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt
  3. 2
      app/src/main/res/values/strings.xml

@ -1,5 +1,6 @@
package net.pokeranalytics.android.ui.adapter package net.pokeranalytics.android.ui.adapter
import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -11,6 +12,7 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.view.BindableHolder import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.getMonthAndYear import net.pokeranalytics.android.util.extensions.getMonthAndYear
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
@ -22,15 +24,16 @@ import kotlin.collections.HashMap
* @param dataSource the datasource providing rows * @param dataSource the datasource providing rows
* @param delegate the delegate, notified of UI actions * @param delegate the delegate, notified of UI actions
*/ */
class HistoryRowRepresentableAdapter( class HistorySessionRowRepresentableAdapter(
var realmResults: RealmResults<Session>,
var delegate: RowRepresentableDelegate? = null, var delegate: RowRepresentableDelegate? = null,
var headers: RealmResults<Session> var realmResults: RealmResults<Session>,
var pendingRealmResults: RealmResults<Session>,
var distinctHeaders: RealmResults<Session>
) : ) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() { RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var headersPositions = HashMap<Int, Date>() private var headersPositions = HashMap<Int, Date?>()
private lateinit var sortedHeaders: SortedMap<Int, Date> private lateinit var sortedHeaders: SortedMap<Int, Date?>
init { init {
refreshData() refreshData()
@ -40,7 +43,7 @@ class HistoryRowRepresentableAdapter(
* Display a session view * Display a session view
*/ */
inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
fun bind(position: Int, row: Session?, adapter: HistoryRowRepresentableAdapter) { fun bind(position: Int, row: Session?, adapter: HistorySessionRowRepresentableAdapter) {
itemView.sessionRow.setData(row as Session) itemView.sessionRow.setData(row as Session)
val listener = View.OnClickListener { val listener = View.OnClickListener {
@ -54,10 +57,10 @@ class HistoryRowRepresentableAdapter(
* Display a session view * Display a session view
*/ */
inner class HeaderTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { inner class HeaderTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
fun bind(position: Int, session: Session?, adapter: HistoryRowRepresentableAdapter) { fun bind(position: Int, title: String, adapter: HistorySessionRowRepresentableAdapter) {
// Title // Title
itemView.findViewById<AppCompatTextView>(R.id.title)?.let { itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
it.text = session?.creationDate?.getMonthAndYear() it.text = title
} }
} }
} }
@ -83,27 +86,45 @@ class HistoryRowRepresentableAdapter(
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
return realmResults.size + headers.size return realmResults.size + pendingRealmResults.size + distinctHeaders.size
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is RowSessionViewHolder) { if (holder is RowSessionViewHolder) {
holder.bind(position, realmResults[getRealIndex(position)], this) holder.bind(position, getSessionForPosition(position), this)
} else if (holder is HeaderTitleViewHolder) { } else if (holder is HeaderTitleViewHolder) {
holder.bind(position, headers[getRealIndex(position)], this) holder.bind(position, getHeaderForPosition(holder.itemView.context, position), this)
} }
} }
/** /**
* Get real index * Return the header
*/ */
private fun getRealIndex(position: Int): Int { private fun getHeaderForPosition(context: Context, position :Int) : String {
if (sortedHeaders.containsKey(position)) { if (sortedHeaders.containsKey(position)) {
// Header position
//Timber.d("getRealIndex: Header: ${sortedHeaders.keys.indexOf(position)}") // If the header has no date, it's a pending session
return sortedHeaders.keys.indexOf(position) return if (sortedHeaders[position] == null) {
context.getString(R.string.pending)
} else {
// Else, return the formatted date
val realmHeaderPosition = if (pendingRealmResults.size > 0) sortedHeaders.keys.indexOf(position) - 1 else sortedHeaders.keys.indexOf(position)
distinctHeaders[realmHeaderPosition]?.startDate?.getMonthAndYear() ?: ""
}
}
return NULL_TEXT
}
/**
* Get real index
*/
private fun getSessionForPosition(position: Int): Session? {
return if (pendingRealmResults.size > 0 && position < pendingRealmResults.size + 1) {
// If we have pending session & the position is between these sessions
pendingRealmResults[position - 1]
} else { } else {
// Else, return the correct session
// Row position // Row position
var headersBefore = 0 var headersBefore = 0
for (key in sortedHeaders.keys) { for (key in sortedHeaders.keys) {
@ -113,8 +134,8 @@ class HistoryRowRepresentableAdapter(
break break
} }
} }
//Timber.d("getRealIndex: Row: $position $headersBefore")
return position - headersBefore realmResults[position - headersBefore - pendingRealmResults.size]
} }
} }
@ -124,17 +145,24 @@ class HistoryRowRepresentableAdapter(
fun refreshData() { fun refreshData() {
headersPositions.clear() headersPositions.clear()
// If we have pending sessions, set the first header to null
if (pendingRealmResults.size > 0) {
headersPositions[0] = null
}
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
var previousYear = 0 var previousYear = Int.MAX_VALUE
var previousMonth = 0 var previousMonth = Int.MAX_VALUE
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
// Add headers if the date doesn't exist yet
for ((index, session) in realmResults.withIndex()) { for ((index, session) in realmResults.withIndex()) {
calendar.time = session.creationDate calendar.time = session.creationDate
if (calendar.get(Calendar.YEAR) == previousYear && calendar.get(Calendar.MONTH) < previousMonth || (calendar.get(Calendar.YEAR) < previousYear) || index == 0) { if (checkHeaderCondition(calendar, previousYear, previousMonth)) {
headersPositions[index + headersPositions.size] = session.creationDate headersPositions[index + headersPositions.size + pendingRealmResults.size] = session.creationDate
previousYear = calendar.get(Calendar.YEAR) previousYear = calendar.get(Calendar.YEAR)
previousMonth = calendar.get(Calendar.MONTH) previousMonth = calendar.get(Calendar.MONTH)
} }
@ -145,5 +173,14 @@ class HistoryRowRepresentableAdapter(
Timber.d("Create viewTypesPositions in: ${System.currentTimeMillis() - start}ms") Timber.d("Create viewTypesPositions in: ${System.currentTimeMillis() - start}ms")
} }
/**
* Check if we need to add a header
* Can be change to manage different condition
*/
private fun checkHeaderCondition(currentCalendar: Calendar, previousYear: Int, previousMonth: Int) : Boolean {
return currentCalendar.get(Calendar.YEAR) == previousYear && currentCalendar.get(Calendar.MONTH) < previousMonth || (currentCalendar.get(Calendar.YEAR) < previousYear)
}
} }

@ -12,7 +12,7 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.activity.SessionActivity import net.pokeranalytics.android.ui.activity.SessionActivity
import net.pokeranalytics.android.ui.adapter.HistoryRowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.HistorySessionRowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
@ -31,9 +31,9 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
} }
} }
private lateinit var historyAdapter: HistoryRowRepresentableAdapter private lateinit var historyAdapter: HistorySessionRowRepresentableAdapter
// Old // Old
//private lateinit var historyAdapter: HistoryRowRepresentableAdapter //private lateinit var historyAdapter: HistorySessionRowRepresentableAdapter
private lateinit var realmSessions: RealmResults<Session> private lateinit var realmSessions: RealmResults<Session>
private val sessions: ArrayList<Session> = ArrayList() private val sessions: ArrayList<Session> = ArrayList()
private val rows: ArrayList<RowRepresentable> = ArrayList() private val rows: ArrayList<RowRepresentable> = ArrayList()
@ -81,22 +81,22 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
* Init data * Init data
*/ */
private fun initData() { private fun initData() {
realmSessions = getRealm().where<Session>().findAll().sort("creationDate", Sort.DESCENDING)
val viewManager = SmoothScrollLinearLayoutManager(requireContext())
realmSessions = getRealm().where<Session>().findAll().sort("startDate", Sort.DESCENDING)
realmSessions.addChangeListener { t, changeSet -> realmSessions.addChangeListener { t, changeSet ->
if (changeSet.insertions.isNotEmpty() || changeSet.deletions.isNotEmpty()) { if (changeSet.insertions.isNotEmpty() || changeSet.deletions.isNotEmpty()) {
historyAdapter.refreshData() historyAdapter.refreshData()
} }
historyAdapter.notifyDataSetChanged() historyAdapter.notifyDataSetChanged()
} }
val months = getRealm().where<Session>().distinct("year", "month").findAll().sort("creationDate", Sort.DESCENDING)
historyAdapter = HistoryRowRepresentableAdapter(realmSessions, this, months)
// Old val startedSessions = getRealm().where<Session>().isNotNull("year").isNotNull("month").findAll().sort("startDate", Sort.DESCENDING)
//historyAdapter = RowRepresentableAdapter(this, this) val pendingSessions = getRealm().where<Session>().isNull("year").isNull("month").findAll().sort("startDate", Sort.DESCENDING)
val distinctDateSessions = getRealm().where<Session>().distinct("year", "month").findAll().sort("startDate", Sort.DESCENDING)
historyAdapter = HistorySessionRowRepresentableAdapter(this, startedSessions, pendingSessions, distinctDateSessions)
val viewManager = SmoothScrollLinearLayoutManager(requireContext())
recyclerView.apply { recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
@ -104,66 +104,6 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
} }
} }
/**
* Create the endedSessions headers
* TODO: Remove
*/
private fun createSessionsHeaders() {
/*
val start = System.currentTimeMillis()
val oldRows = ArrayList<RowRepresentable>()
oldRows.addAll(rows)
rows.clear()
sessions.clear()
sessions.addAll(getRealm().copyFromRealm(realmSessions))
noSessionFound.isVisible = sessions.isEmpty()
GlobalScope.launch {
val groupedByDay = false
val calendar = Calendar.getInstance()
val currentCalendar = Calendar.getInstance()
for ((index, session) in sessions.withIndex()) {
currentCalendar.time = session.creationDate
if (groupedByDay) {
if (!calendar.isSameDay(currentCalendar) || index == 0) {
calendar.time = currentCalendar.time
val header = CustomizableRowRepresentable(
customViewType = RowViewType.HEADER_TITLE,
title = session.creationDate.longDate()
)
rows.add(header)
}
} else {
if (!calendar.isSameMonth(currentCalendar) || index == 0) {
calendar.time = currentCalendar.time
val header = CustomizableRowRepresentable(
customViewType = RowViewType.HEADER_TITLE,
title = session.creationDate.getMonthAndYear()
)
rows.add(header)
}
}
rows.add(session)
}
val diffResult = DiffUtil.calculateDiff(HistorySessionDiffCallback(rows, oldRows))
historyAdapter.updateRows(diffResult)
if (newSessionCreated) {
newSessionCreated = false
recyclerView.smoothScrollToPosition(0)
}
Timber.d("createSessionsHeaders in: ${System.currentTimeMillis() - start}ms")
}
*/
}
override fun rowRepresentableForPosition(position: Int): RowRepresentable? { override fun rowRepresentableForPosition(position: Int): RowRepresentable? {
return this.rows[position] return this.rows[position]
} }

@ -31,6 +31,8 @@
<string name="tournament_feature">Tournament Feature</string> <string name="tournament_feature">Tournament Feature</string>
<string name="new_entity">New</string> <string name="new_entity">New</string>
<string name="pending">Pending</string>
<!-- Translated --> <!-- Translated -->
<string name="_ago">%s ago</string> <string name="_ago">%s ago</string>

Loading…
Cancel
Save