Как связать представление в RecyclerView.ViewHolder с kotlin
Что меня озадачивает, так это как связать вид в Recycleler.ViewHolder
.
Это мой простой адаптер и как преобразовать его в kotlin использовать kotlin-android-extensions
без 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);
}
}
Ответы
Ответ 1
опубликовано решение работает, но я хотел бы что-то добавить к нему. Цель шаблона зрителя состоит в том, чтобы сделать только дорогие вызовы findViewById
один раз для каждого представления, а затем удерживать эти ссылки внутри ViewHolder
и получать доступ к ним из них, когда вам нужно связать их.
Однако вызов holder.itemView.tv_title.text
в методе onBindViewHolder
приведет к вызову findViewById
для поиска View
, который имеет id tv_title
в пределах itemView
каждый раз, когда привязывается к объекту. Это в основном устраняет прирост производительности и идею кэширования, для которой предназначены пользователи.
Вы можете одновременно использовать шаблон зрителя и Kotlin Android Extensions, добавив свойство к вашему ViewHolder
и инициализируя его вызовом, сделанным с помощью расширений, например:
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val title = itemView.tv_title
}
Затем вы можете получить доступ к View
через это свойство:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.title.text = mRooms!!.get(position).getLocation()
holder.itemView.setOnClickListener { v ->
mListener?.onItemClickListener(v, holder.layoutPosition)
}
}
Наконец, я бы предложил избавиться от оператора !!
и вместо этого выполнить нулевую проверку:
mRooms?.let { rooms ->
holder.title.text = rooms[position].getLocation()
}
Ответ 2
Просто убедитесь, что у вас есть apply plugin: 'kotlin-android-extensions'
в вашем приложении gradle файл (а не ваш root gradle), а затем просто используйте файл Convert Java для ярлыка файла Kotlin. Удалите код Butterknife и прямо ссылайтесь на itemView.tv_title
на свой ViewHolder
объект.
Изменить. Я изменил код, чтобы воспользоваться кэшированием синтетического вида Kotlin, вам не нужно устанавливать переменную, равную представлению типа val title = itemView.tv_title
, чтобы получить эти преимущества
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)
}
}
Ответ 3
Другие ответили на вопрос достаточно хорошо, я просто хотел добавить, что в class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
не должно быть оператора с нулевым значением ('?
') после itemView
для привязки kotlin к работе.
Android Studio автоматически добавляет этот оператор с нулевым значением при использовании автозаполнения для добавления параметров конструктора из ViewHolder(itemView)
.