Last active
June 26, 2020 13:31
-
-
Save 4xes/3d69bfdcf8093bfdad02229d98e4fed2 to your computer and use it in GitHub Desktop.
Empty state cursor recycler adapter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.efectum.ui.base.adapter | |
import android.util.Log | |
import android.database.Cursor | |
import android.database.DataSetObserver | |
import androidx.recyclerview.widget.RecyclerView | |
abstract class CursorAdapter<VH : RecyclerView.ViewHolder>(cursor: Cursor?) : RecyclerView.Adapter<VH>() { | |
var cursor: Cursor? = null | |
private set | |
protected var dataValid: Boolean = false | |
private var rowIdColumn: Int = 0 | |
private val dataSetObserver: DataSetObserver? | |
init { | |
this.cursor = cursor | |
dataValid = cursor != null | |
rowIdColumn = if (dataValid) this.cursor!!.getColumnIndex("_id") else -1 | |
dataSetObserver = NotifyingDataSetObserver() | |
if (this.cursor != null) { | |
this.cursor!!.registerDataSetObserver(dataSetObserver) | |
} | |
} | |
override fun getItemCount(): Int { | |
if (dataValid) { | |
return cursor?.count ?: 0 | |
} | |
return 0 | |
} | |
override fun getItemId(position: Int): Long { | |
if (dataValid && cursor != null && cursor!!.moveToPosition(position)) { | |
return cursor!!.getLong(rowIdColumn) | |
} | |
return 0 | |
} | |
override fun setHasStableIds(hasStableIds: Boolean) { | |
super.setHasStableIds(true) | |
} | |
abstract fun onBindViewHolder(viewHolder: VH, cursor: Cursor) | |
override fun onBindViewHolder(viewHolder: VH, position: Int) { | |
if (moveCursorToPosition(position)) { | |
onBindViewHolder(viewHolder, cursor!!) | |
} | |
} | |
protected fun moveCursorToPosition(position: Int): Boolean { | |
if (!dataValid) { | |
Log.e("Error", "this should only be called when the cursor is valid") | |
return false | |
} | |
if (!cursor!!.moveToPosition(position)) { | |
Log.e("Error", "couldn't move cursor to position $position") | |
return false | |
} | |
return true | |
} | |
/** | |
* Change the underlying cursor to a new cursor. If there is an existing cursor it will be | |
* closed. | |
*/ | |
fun changeCursor(cursor: Cursor) { | |
swapCursor(cursor)?.close() | |
} | |
/** | |
* Swap in a new Cursor, returning the old Cursor. Unlike | |
* [.changeCursor], the returned old Cursor is *not* | |
* closed. | |
*/ | |
private fun swapCursor(newCursor: Cursor): Cursor? { | |
if (newCursor === cursor) { | |
return null | |
} | |
val oldCursor = cursor | |
if (dataSetObserver != null) { | |
oldCursor?.unregisterDataSetObserver(dataSetObserver) | |
} | |
cursor = newCursor | |
if (cursor != null) { | |
if (dataSetObserver != null) { | |
cursor!!.registerDataSetObserver(dataSetObserver) | |
} | |
rowIdColumn = newCursor.getColumnIndexOrThrow("_id") | |
dataValid = true | |
notifyDataSetChanged() | |
} else { | |
rowIdColumn = -1 | |
dataValid = false | |
notifyDataSetChanged() | |
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter | |
} | |
return oldCursor | |
} | |
private inner class NotifyingDataSetObserver : DataSetObserver() { | |
override fun onChanged() { | |
super.onChanged() | |
dataValid = true | |
notifyDataSetChanged() | |
} | |
override fun onInvalidated() { | |
super.onInvalidated() | |
dataValid = false | |
notifyDataSetChanged() | |
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.efectum.ui.base.adapter | |
import android.database.Cursor | |
import android.view.View | |
import android.view.ViewGroup | |
import androidx.recyclerview.widget.RecyclerView | |
abstract class EmptySearchCursorAdapter<VH : RecyclerView.ViewHolder>(cursor: Cursor?) : CursorAdapter<RecyclerView.ViewHolder>(cursor) { | |
override fun getItemViewType(position: Int) = if (super.getItemCount() == 0) { | |
TYPE_EMPTY | |
} else { | |
TYPE_ITEM | |
} | |
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { | |
TYPE_ITEM -> { | |
onCreateViewItemHolder(parent) | |
} | |
else -> { | |
onCreateViewEmptyHolder(parent) | |
} | |
} | |
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) { | |
when (getItemViewType(position)) { | |
TYPE_ITEM -> { | |
if (moveCursorToPosition(position)) { | |
@Suppress("UNCHECKED_CAST") | |
onBindViewItemHolder(viewHolder as VH, cursor!!) | |
} | |
} | |
} | |
} | |
open fun onCreateViewEmptyHolder(parent: ViewGroup): RecyclerView.ViewHolder { | |
return EmptyHolder(View(parent.context)) | |
} | |
abstract fun onBindViewItemHolder(holder: VH, cursor: Cursor) | |
abstract fun onCreateViewItemHolder(parent: ViewGroup): VH | |
override fun getItemCount(): Int { | |
val itemCount = super.getItemCount() | |
if (itemCount == 0) { | |
return 1 | |
} | |
return itemCount | |
} | |
class EmptyHolder(itemView: View) : RecyclerView.ViewHolder(itemView) | |
companion object { | |
const val TYPE_EMPTY = 0 | |
const val TYPE_ITEM = 1 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment