I'm currently experimenting with a RecyclerViewer, but stumbled upon a problem: When I update the data and call notifyDataSetChanged, the RecyclerViewer updates it's view, but not with the new data, but rather with the old data.
I've searched through Stackoverflow for the problem, but in most cases the problem is that they either created two instances of the adapter (reference) or that they don't have a layout manager, and I believe that neither of those is my problem.
Here is my code for creating and updating the RecyclerViewer in the fragment in which it's hosted:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_player_list_list, container, false)
data = getPlayersAsList(requireContext(), gameUUID)
if(data.isEmpty()){
data = listOf(SharedPreferencesManager.Companion.Player("John", false))
}
// Set the adapter
if(view is LinearLayout){
view.children.forEach {
if (it is RecyclerView) {
with(it) {
layoutManager = when {
columnCount <= 1 -> LinearLayoutManager(context)
else -> GridLayoutManager(context, columnCount)
}
Log.i("DEBUG", "The first adapter was called")
adapter = MyItemRecyclerViewAdapter(data)
}
}
}
}
fun notifyDataUpdate(position: Int? = null) {
if(view is LinearLayout){
(view as LinearLayout).children.forEach {
if(it is RecyclerView){
data = getPlayersAsList(requireContext(), gameUUID)
Log.i("DATA UPDATE", "Player list is now $data")
it.adapter?.notifyDataSetChanged()
}
}
}
}
And here is the code of the adapter:
import android.util.Log
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import com.chuaat.hideandseek.databinding.FragmentPlayerListBinding
import com.google.android.material.button.MaterialButton
import java.util.*
/**
* [RecyclerView.Adapter] that can display a [PlaceholderItem].
* TODO: Replace the implementation with code for your data type.
*/
class MyItemRecyclerViewAdapter(
private val values: List<SharedPreferencesManager.Companion.Player>
) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
FragmentPlayerListBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = values[position]
Log.i("RECYCLER VIEWER", "SETTING VALUE OF $item")
if(item.isSeeker){
holder.buttonView.setIconResource(R.drawable.ic_baseline_search_24)
}
else{
holder.buttonView.setIconResource(R.drawable.ic_outline_visibility_off_24)
}
holder.contentView.text = item.name
}
override fun getItemCount(): Int = values.size
inner class ViewHolder(binding: FragmentPlayerListBinding) :
RecyclerView.ViewHolder(binding.root) {
val buttonView: MaterialButton = binding.toggleSeekerButton as MaterialButton
val contentView: TextView = binding.content
override fun toString(): String {
return super.toString() + " '" + contentView.text + "'"
}
}
}
The log output I get when calling notifiyDataUpdate is:
I/DATA UPDATE: Player list is now [Player(name=Joe, isSeeker=false)]
I/RECYCLER VIEWER: SETTING VALUE OF Player(name=John, isSeeker=false)
As you can see the updated data is with a Player named Joe, but in onBindViewHolder the only value is the default Player ("John").
What is the problem I'm missing?