The first data node that is immediately there under user id will contain a linked list type data. Each index can contain two parts: data and info. The confusion is due to the unique key -MkqHbtLzqzI... which is there immediately under index data. Each index data will have a list of such a different and dynamic key. Matrix
is a List<Float>
.
We want to use FirebaseRecyclerAdapter
where I will be required to give the type of class under setQuery
method. But I am confused how to make equivalent pojo class (or data class in kotlin) of such a structure.
Objects that we want to load in a recyclerView starts from 2
. So, 6154...
is a userId
under which we have a node called data
as shown in the given screenshot. This data
contains a list of items in a linkedList<Long>
fashion that we want to display in a recyclerView
.
I have tried with below data classes
but the problem is, it neither contains the index
( 2
in screenshot) nor the unique key ( -MkqH...
).
UserData ( A class that I am using for firebaseRecyclerViewAdapter
)
@Keep
@IgnoreExtraProperties
data class UserData(
var data: UserPrefsData? = null,
var info: UserPrefsInfo? = null
) {
@Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
"data" to data,
"info" to info
)
}
}
UserPrefsData
@Keep
@IgnoreExtraProperties
data class UserPrefsData(
var color: String = BRUSH_BLACK,
var stroke: Float = 8f,
var data: String = "",
var shape: Shape? = null,
var fill: Boolean = false,
var matrix : ArrayList<Float>? = null
) {
@Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
"color" to color,
"stroke" to stroke,
"data" to data,
"shape" to shape,
"fill" to fill,
"matrix" to matrix
)
}
}
UserPrefsInfo
@Keep
@IgnoreExtraProperties
data class PageInfo(
var color: String = BRUSH_WHITE,
var backGround: BackGround = BackGround.COLOR,
var orientation: Int = ORIENTATION_PORTRAIT,
var previous: Int = -1,
var next: Int = -1
) {
@Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
"color" to color,
"backGround" to backGround,
"orientation" to orientation,
"previous" to previous,
"next" to next
)
}
}
Activity
private fun initFirebaseAdapter(): FirebaseAdapter? {
val userDataRef = databaseReference.child("data")
val options = FirebaseRecyclerOptions.Builder<UserData>()
.setLifecycleOwner(this)
.setQuery(userDataRef, UserData::class.java)
.build()
return FirebaseAdapter(
options,
isAdmin,
rvItemEventListener
)
}
private fun setRecyclerViewAdapter(
recyclerView: RecyclerView?,
recyclerViewAdapter: RecyclerView.Adapter<out RecyclerView.ViewHolder>?
) {
recyclerView?.adapter = recyclerViewAdapter
}
rvFirebaseAdapter = initFirebaseAdapter()
setRecyclerViewAdapter(binding.idVRv, rvFirebaseAdapter)
FirebaseAdapter
class FirebaseAdapter(var options: FirebaseRecyclerOptions<UserData>,
val showDeleteOption: Boolean,
private val callbackListener: Callbacks.RecyclerViewItemCallback):
FirebaseRecyclerAdapter<UserData, FirebaseAdapter.UserViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.user_item, parent, false)
val binding = UserItemBinding.bind(itemView)
return UserViewHolder(binding, itemView)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :onBindViewHolder: position: $position item: ${getItem(position)} _getting data here - it is working_")
if (position != RecyclerView.NO_POSITION) {
bindData(holder, position)
}
}
private fun bindData(holder: UserViewHolder, position: Int) {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :bindData: position: $position" _This is also working_)
holder.binding.idVTvPageNumber.text = (position + 1).toString()
}
override fun getItemCount(): Int {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :superGetItemCount: ${super.getItemCount()}")
return super.getItemCount()
}
inner class UserViewHolder(val binding: UserItemBinding, itemView: View): RecyclerView.ViewHolder(itemView) {
init {
if (showDeleteOption) {
binding.idVIvDelete.setOnClickListener {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: UserViewHolder: :bindingAdapterPosition: $bindingAdapterPosition absoluteAdapterPosition: $absoluteAdapterPosition" _This is working_)
onDeleteItem(adapterPosition, binding.idVIvDelete)
}
} else {
binding.idVIvDelete.visibility = View.GONE
}
}
}
private fun onDeleteItem(adapterPosition: Int, idVIvDelete: View) {
if (adapterPosition != RecyclerView.NO_POSITION) {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :onDeleteItem: position: $adapterPosition" _This is also working_)
val item = getItem(adapterPosition)
getRef(adapterPosition).removeValue()
callbackListener.onDeleteItem(adapterPosition, item, idVIvDelete, itemCount)
notifyItemRemoved(adapterPosition)
}
}
override fun onBindViewHolder(
holder: UserViewHolder,
position: Int,
model: UserData
) {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :onBindViewHolder: firebase: position: $position UserData: $model" _This is never being called_)
if (position != RecyclerView.NO_POSITION) {
bindData(holder, position)
}
}
override fun onChildChanged(
type: ChangeEventType,
snapshot: DataSnapshot,
newIndex: Int,
oldIndex: Int
) {
super.onChildChanged(type, snapshot, newIndex, oldIndex)
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :onChildChanged: snapshot: $snapshot" _This is working_)
}
override fun onDataChanged() {
super.onDataChanged()
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :onDataChanged: ")
}
override fun onError(error: DatabaseError) {
super.onError(error)
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :onError: $error")
}
override fun getItem(position: Int): UserData {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :getItem: position: $position")
return super.getItem(position)
}
override fun getRef(position: Int): DatabaseReference {
Timber.d(" :$LOG_APP_NAME: FirebaseAdapter: :getRef: position: $position")
return super.getRef(position)
}
}
Update: 06th Oct 2021
_The default onBindViewHolder
is calling onBindViewHolder
of FirebaseRecyclerAdapter
and in our implementation, there was no super call. Hence, after removing onBindViewHolder(holder: UserViewHolder, position: Int)
, onBindViewHolder(holder: UserViewHolder, position: Int, model: UserData)
is getting called. But I still do not know how to get those indices and unique keys .
Thank you in anticipation. Any reference link, suggestion, guidance will also be helpful.
For such nested data, we can use a SnapshotParser
. Also, in order to fulfil the requirements, I had to change data class as below:
UserData
@Keep
@IgnoreExtraProperties
data class UserData(
@Exclude
var dataIndex: Long? = null,
@Exclude
var userDataItemKey: String? = null,
@Exclude
var listOfUserPrefsData: MutableList<UserPrefsData?>? = null,
@JvmField
@PropertyName(AppFirebase.DATA)
var data: UserPrefsData? = null,
@JvmField
@PropertyName(AppFirebase.INFO)
var userPrefsInfo: UserPrefsInfo? = null
) {
@Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
"data" to data,
"info" to userPrefsInfo
)
}
}
After that, I have used SnapshotParser
as below:
private fun initFirebaseAdapter(): FirebaseAdapter? {
val userDataRef = databaseReference.child(AppFirebase.DATA)
val options = FirebaseRecyclerOptions.Builder<UserData>()
.setLifecycleOwner(this)
.setQuery(userDataRef) {
val userPrefsInfo: UserPrefsInfo?
var userDataItemKey: String? = null
val listOfUserPrefsData = mutableListOf<UserPrefsData?>()
val dataIndex = it.key?.toLong()
val userPrefsInfoRef = it.child(AppFirebase.INFO)
userPrefsInfo = userPrefsInfoRef.getValue<UserPrefsInfo>()
val userPrefsDataRef = it.child(AppFirebase.DATA)
for (userDataItem in userPrefsDataRef.children) {
userDataItemKey = userDataItem.key
val userPrefsData = userDataItem.getValue<UserPrefsData>()
userPrefsData?.userDataItemKey = userDataItemKey
listOfUserPrefsData.add(userPrefsData)
}
UserData(
dataIndex = dataIndex,
userDataItemKey = userDataItemKey,
listOfUserPrefsData = listOfUserPrefsData,
userPrefsInfo = userPrefsInfo
)
}
.build()
return FirebaseAdapter(
options,
isAdmin,
rvWhiteboardItemEventListener
)
}
Now I have that 2
indices, that list of -Mkq...
unique keys including UserPrefsData
and UserPrefsInfo
for each index. So, basically, everything that is there under data
of 6154...
including indices and unique keys...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.