android - studio - kotlin example
Cómo enlazar la vista en RecyclerView.ViewHolder con kotlin (3)
La solución publicada funciona, pero me gustaría agregarle algo. El propósito del patrón de marcador de vista es hacer solo las costosas llamadas findViewById
una vez por cada vista, y luego mantener esas referencias dentro de ViewHolder
y acceder a las vistas desde allí siempre que necesite enlazar una.
Sin embargo, llamar a holder.itemView.tv_title.text
en el método onBindViewHolder
causará que una llamada findViewById
encuentre la View
que tiene el id tv_title
dentro del itemView
cada vez que el visor está vinculado. Básicamente, esto elimina las ganancias de rendimiento y la idea de almacenamiento en caché para las que están los espectadores.
Puede utilizar el patrón de marcador de vista y las extensiones de Android de Kotlin al mismo tiempo agregando una propiedad a su ViewHolder
e inicializándola con una llamada realizada con extensiones, como por ejemplo:
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val title = itemView.tv_title
}
A continuación, puede acceder a la View
través de esta propiedad:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.title.text = mRooms!!.get(position).getLocation()
holder.itemView.setOnClickListener { v ->
mListener?.onItemClickListener(v, holder.layoutPosition)
}
}
Por último, sugiero deshacerse de la !!
operador, y en su lugar realiza una comprobación nula:
mRooms?.let { rooms ->
holder.title.text = rooms[position].getLocation()
}
Lo que me desconcierta es cómo enlazar la vista en Recycleler.ViewHolder
. ¿Este es mi adaptador simple y cómo convertirlo a kotlin usar kotlin-android-extensions
sin 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);
}
}
Otros respondieron la pregunta bastante bien, solo quería agregar que en la class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
no debería haber un operador que itemView
contener itemView
('' ?
'') Después de itemView
para que el enlace de kotlin funcione.
Android Studio agrega automáticamente ese operador anulable al usar autocompletar para agregar parámetros de constructor desde ViewHolder(itemView)
.
Solo asegúrate de apply plugin: ''kotlin-android-extensions''
en tu archivo de aplicación gradle (no tu raíz gradle) y luego solo usa el archivo Convertir archivo Java al archivo Kotlin. Elimine el código de Butterknife y itemView.tv_title
referencia directamente a itemView.tv_title
en su objeto ViewHolder
como tal.
Edición : he cambiado el código para aprovechar el almacenamiento en caché de la vista sintética de Kotlin, no es necesario establecer una variable igual a una vista como val title = itemView.tv_title
para obtener esos beneficios
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)
}
}