Подтвердить что ты не робот

Как связать представление в 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);
  }

}
4b9b3361

Ответ 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).