Comment lier la vue dans RecyclerView.ViewHolder avec kotlin
Ce qui me rend perplexe c'est comment lier la vue en Recycleler.ViewHolder
.
C'est mon adaptateur simple et comment le convertir en kotlin utiliser kotlin-android-extensions
sans ButterKnife
?
public class RoomAdapter extends RecyclerView.Adapter<ViewHolder> {
private OnItemClickListener mListener;
private List<LocationBean> mRooms;
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tv_title)
TextView tvTitle;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
public void setData(List<LocationBean> rooms) {
mRooms = rooms;
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_first_select, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.tvTitle.setText(mRooms.get(position).getLocation());
holder.itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.onItemClickListener(v, holder.getLayoutPosition());
}
});
}
@Override
public int getItemCount() {
return mRooms == null ? 0 : mRooms.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public interface OnItemClickListener {
void onItemClickListener(View v, int pos);
}
}
3 réponses
solution postée ça marche, mais j'aimerais y ajouter quelque chose. Le but du modèle de titulaire de vue est de rendre seulement le findViewById
appelle une fois pour chaque vue, puis garde ces références à l'intérieur du ViewHolder
, et accédez aux vues à partir de là chaque fois que vous avez besoin d'en lier une.
Toutefois, appeler holder.itemView.tv_title.text
dans le onBindViewHolder
méthode provoque un findViewById
appel pour trouver l' View
qui a l'id tv_title
dans le itemView
chaque fois que le viewholder est lié. Cela élimine essentiellement les gains de performance et l'idée de mise en cache que les visualiseurs sont pour.
vous pouvez utiliser les Extensions viewholder et Kotlin Android en même temps en ajoutant une propriété à votre ViewHolder
, et l'initialiser avec un appel à l'aide d'Extensions, comme suit:
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val title = itemView.tv_title
}
alors vous pouvez accéder au View
grâce à cette propriété:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.title.text = mRooms!!.get(position).getLocation()
holder.itemView.setOnClickListener { v ->
mListener?.onItemClickListener(v, holder.layoutPosition)
}
}
enfin, je suggère de se débarrasser de la !!
l'opérateur, et en faisant un nul vérifier à la place:
mRooms?.let { rooms ->
holder.title.text = rooms[position].getLocation()
}
assurez-vous juste que vous avez apply plugin: 'kotlin-android-extensions'
dans le fichier gradle de votre application (pas votre gradle racine) et ensuite il suffit d'utiliser le fichier Java convertir en raccourci de fichier Kotlin. Supprimer le code Butterknife et faire directement référence à itemView.tv_title
dans votre ViewHolder
objet comme si.
Modifier: j'ai changé le code pour profiter du cache de vue synthétique de Kotlin, vous n'avez pas besoin de définir une variable égale à une vue comme val title = itemView.tv_title
afin d'obtenir ces avantages
import kotlinx.android.synthetic.main.item_first_select.view.*
class RoomAdapter : RecyclerView.Adapter<RoomAdapter.ViewHolder>() {
private var listener: OnItemClickListener? = null
private var rooms: List<LocationBean>? = null
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(room: Room) {
itemView.tv_title.text = room.getLocation()
}
}
fun setData(rooms: List<LocationBean>) {
this.rooms = rooms
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_first_select, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
rooms?.get(position)?.let { room ->
holder.bind(room)
}
holder.itemView.setOnClickListener { v ->
listener?.onItemClickListener(v, holder.layoutPosition)
}
}
override fun getItemCount(): Int {
return rooms?.size ?: 0
}
fun setOnItemClickListener(listener: OnItemClickListener) {
this.listener = listener
}
interface OnItemClickListener {
fun onItemClickListener(v: View, pos: Int)
}
}
D'autres ont très bien répondu à la question, je voulais juste ajouter que dans class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
il ne devrait pas y avoir d'opérateur nul ('?
') après itemView
pour que Kotlin binding fonctionne.
Android Studio ajoute automatiquement cet opérateur nullable lorsque vous utilisez autocomplete pour ajouter des paramètres de constructeur à partir de ViewHolder(itemView)
.