Как добавить onClickListener в RecyclerView, используя привязку данных - PullRequest
0 голосов
/ 05 апреля 2020

Я только начал использовать databinding, теперь я застрял, реализуя прослушиватель щелчков привязки данных в recyclerView. У меня это работает так:

  @NonNull
    @Override
    public BookViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ItemBookCoversBinding binding = ItemBookCoversBinding.inflate(LayoutInflater.from(context), parent, false);
        final BookViewHolder bookViewHolder = new BookViewHolder(binding);
        bookViewHolder.binding.bookDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.deleteCover(bookViewHolder.getAdapterPosition());
            }
        });
        bookViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.changeCover(bookViewHolder.getAdapterPosition());
            }
        });
        return bookViewHolder;
    }

, что буквально работает нормально, но я не использую databinding для clickListener. Я попытался добавить переменную позицию в свой макет, как это:

   <data>

        <variable
            name="position"
            type="int" />

        <variable
            name="listener"
            type="....interfaces.Listener" />


    </data>
    <ImageView
        android:id="@+id/book_cover"
        coverImage="@{bookImages.storageRef}"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_green_dark"
        android:onClick="@{() -> listener.changeCover(position)}"
        android:src="@drawable/placeholder" />

и в onCreateViewHolder в адаптере это:

bookViewHolder.binding.setVariable(BR.position, bookViewHolder.getAdapterPosition());

или это:

 binding.setPosition(bookViewHolder.getAdapterPosition());

onClick работает как и ожидалось в обоих случаях, но bookViewHolder.getAdapterPosition() возвращает -1, NO_POSITION

Чего мне здесь не хватает? Каков наилучший способ реализации databinding onClickListener в RecyclerView?

У меня уже есть кое-что, что работает, но это не databinding способ.

Ответы [ 3 ]

0 голосов
/ 05 апреля 2020

Похоже, когда вы делаете data binding в адаптере, вы хотите установить переменные, которые будут запускать clickListener, вместе с методом привязки данных, который вы выбираете для заполнения каждого элемента. Поскольку это переменный, а не метод.

0 голосов
/ 09 мая 2020

Реализация Click Listeners в адаптере является стандартным кодом для разработчика.

  • Необходимо создать интерфейс в адаптере, реализовать его из действия / фрагмента и вызвать его из файла xml, как вы хотите интегрировать с привязкой данных.

Вот ссылка, по которой лучше всего реализовать прослушиватели кликов.

0 голосов
/ 05 апреля 2020

Это не работает, потому что вы назначаете переменные во время создания представления. В этот момент ваши ViewHolder s не имеют позиции адаптера. Я не знаю, как именно они работают, но всякий раз, когда я пытался использовать его вне прослушивателей кликов, он всегда возвращал -1. Они не привязаны к RecyclerView в данный момент, поэтому вы не получите его без какой-либо асинхронной работы или layoutChangeListeners, и, вероятно, он всегда будет равен -1 в onCreateViewHolder

. ViewHolder Позиция с другого места. Вы можете получить это с помощью переменной viewType после переопределения метода getItemViewType(int pos) следующим образом:

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @NonNull
    @Override
    public PlaylistViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewTypeButActuallyItIsPosition) {
        ...
        binding.setPosition(viewTypeButActuallyItIsPosition);
        ...
    }

Edit

Одна проблема, с которой вы можете столкнуться при таком подходе ( и мне кажется, что вы, вероятно, так и сделаете) в том, что ImageView s будет иметь неправильные позиции, установленные при утилизации ViewHolders, так как методы onBindViewHolder будут вызываться без вызова onCreateViewHolder, пользовательский интерфейс будет изменен, но привязка будет переменная останется прежней, поэтому правильным способом будет назначение этой позиции в методе onBindViewHolder. Это означает, что вы должны хранить привязку в классе ViewHolder и публиковать ее c, чтобы вы могли получить к ней доступ в onBindViewHolder

    @Override
    public void onBindViewHolder(@NonNull YourViewHolder holder, int i) {
        ...
        holder.binding.setPosition(i);
    }
...