Premise
An Android school project which uses different APIs to get a list of all Pokémons and information about them. This specific piece of code relates to a list of all pokémons, or a Pokédex.
Specifically, a RecyclerAdapter
which sets the OnClickListener
for each
row to the same thing:
class PokedexRecyclerAdapter(val context: Context,
val data: MutableList<PokedexEntry>):
RecyclerView.Adapter<PokedexRecyclerAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val rowView : View = LayoutInflater.from(context)
.inflate(R.layout.pokedex_list_item, parent, false)
rowView.setOnClickListener{
(context as MainActivity).onEntryListClicked(it.tag.toString())
}
return ViewHolder(rowView)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// [...]
}
}
Problem
As each row of the RecyclerView
is a different pokémon, in some specific
fragments I needed to change the callback to a specific method call for
each entry.
The method I needed to call looked as follows:
private fun setUpSelectedPokemon(data: PokedexEntry) {
selectedPokemon = data
// Clear second type if new pokémon only has one
resetSelectedPokemon(data)
selectedPokemonNameTextView.text = data.name
// [...] More code that configures the selected Pokémon layout elements
}
Solution
The first step to fix this is to pass the callback as an argument to the
RecyclerAdapter
although the main fix comes from moving the assignment
of the callback from
onCreateViewHolder()
to
onBindViewHolder()
which has access to the
ViewHolder
and the position of the element in the list.
So the RecyclerAdapter
now looks like this:
class PokedexRecyclerAdapter(val context: Context,
val data: MutableList<PokedexEntry>,
val callback: ((PokedexEntry) -> Unit)? = null):
RecyclerView.Adapter<PokedexRecyclerAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val rowView : View = LayoutInflater.from(context)
.inflate(R.layout.pokedex_list_item, parent, false)
return ViewHolder(rowView)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// [...]
if (callback != null) {
holder.itemView.setOnClickListener{
callback!!(data[position])
}
} else {
holder.itemView.setOnClickListener{
(context as MainActivity).onEntryListClicked(it.tag.toString())
}
}
}
}
Which can then be called like this from our Fragment
:
pokemonListRecyclerView.adapter =
PokedexRecyclerAdapter(activity as MainActivity, data)
{ elt -> setUpSelectedPokemon(elt) }