Интерфейс в адаптере - PullRequest
0 голосов
/ 26 марта 2019

Изучая Kotlin, я хочу реализовать интерфейс на адаптере, который будет уведомлять об активности при нажатии на элемент.Ничего не работает, мне нужна ваша помощь.

Если я пишу Java, я делаю это следующим образом: (интерфейс: OnAnimalClickListener):

Адаптер:

public class PackContentAdapter extends RecyclerView.Adapter<PackContentAdapter.ViewHolder> {
    private Context context;
    private OnAnimalClickListener onAnimalClickListener;
    ...
    void setOnAnimalClickListener(OnAnimalClickListener onAnimalClickListener) {
        this.onAnimalClickListener = onAnimalClickListener;
    }
    ...

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        holder.bind(item);
    }
    ...
    class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        ...
        ViewHolder(View view) {
            super(view);
            ...
        }

        void bind(Item item) {
            ...             
        }

        @Override
        public void onClick(View v) {
            onAnimalClickListener.onAnimalClicked();
        }
    }

    public interface OnAnimalClickListener {
        void onAnimalClicked();
    }
}

Активность:

contentAdapter.setOnAnimalClickListener(() -> //doSomething);

Это я пишу на Kotlin (имена изменены):

Адаптер:

class PacksAdapter : RecyclerView.Adapter<PacksAdapter.ViewHolder>() {

    var onPackClickListener: OnPackClickListener? = null
        set(value) {
            field = value
        }

    var packList: ArrayList<Animal> = ArrayList()
        set(value) {
            field = value
            notifyDataSetChanged()
        }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.cell_animalpack_4, parent, false))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(packList[0], context)
    }


 class ViewHolder(view: View) : RecyclerView.ViewHolder(view),View.OnClickListener {
        ...
        fun bind(pack: AnimalPackFull, context: Context) {
            ...
        }

        override fun onClick(v: View?) {
            onPackClickListener.
        }
    }

    interface OnPackClickListener {
        fun onPackClicked(packId: Int)
    }
}

Активность:

(recycler_packs.adapter as PacksAdapter).onPackClickListener = PacksAdapter.OnPackClickListener()

Myвопросы:

1) Я специально не завершаю свой код здесь:

 override fun onClick(v: View?) {
                onPackClickListener.
            }

Из-за того, что я не вижу свой onPackClickListener от onClick, IDE пишет, что он Unresolved,Почему?

2) Я получил ошибку об активности:

введите сюда описание изображения

Я могу понять, что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 26 марта 2019

Более простой в использовании обратный вызов kotlin:

В вашем адаптере:

    class LEventsAdapter(
    private val items: MutableList<EventDetailItem> = ArrayList(),
    private val callback: (id: String, distance: String) -> Unit
) : RecyclerView.Adapter<LEventsAdapter.LEventsViewHolder>() {

    override fun getItemCount(): Int = items.size

 ...

В вашем видоискателе в вызове onclick: callback.invoke(id, distance)

А в своей деятельности реализуй свой обратный вызов:

recView.adapter = LEventsAdapter(items, callback = { id, distance -> 
  //your code here
})
0 голосов
/ 26 марта 2019

Вы увидите onPackClickListener, только если объявите вложенный класс как inner класс (см .: https://kotlinlang.org/docs/reference/nested-classes.html).

Однако я предлагаю передать слушатель классу ViewHolder в качестве аргумента и вызвать этот параметр, что-то вроде этого:

inner class ViewHolder(view: View, itemClickListener: OnPackClickListener?) : RecyclerView.ViewHolder(view), View.OnClickListener {

    fun bind(pack: AnimalPackFull, context: Context) { ... }

    override fun onClick(v: View?) {
        onPackClickListener?.onPackClicked(...)
    }
}

Другая проблема заключается в том, что вы должны создать этот интерфейс, реализовав его, потому что вы не можете просто создать его экземпляр:

val listener = object : OnPackClickListener {
        override fun onPackClicked(packId: Int) {
            TODO("not implemented")
        }
    }

Предложение здесь. Приятной особенностью Kotlin является то, что вы можете переключать интерфейсы с одним методом на lambdas (см .: https://kotlinlang.org/docs/reference/lambdas.html). Код может быть изменен на что-то вроде этого:

class PacksAdapter : RecyclerView.Adapter<PacksAdapter.ViewHolder>() {

var onPackClickListener: ((Int) ->Unit)? = null
    set(value) {
        field = value
    }

var packList: ArrayList<Animal> = ArrayList()
    set(value) {
        field = value
        notifyDataSetChanged()
    }

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {

    return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.cell_animalpack_4, parent, false), onPackClickListener)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(packList[0], context)
}


class ViewHolder(view: View, private val itemClickListener: ((Int) ->Unit)?) : RecyclerView.ViewHolder(view), View.OnClickListener {

    fun bind(pack: AnimalPackFull, context: Context) { ... }

    override fun onClick(v: View?) {
        itemClickListener?.invoke(...)
    }
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...