Сравнение view.setOnLongClickListener и view.onClick в Kotlin

Я пытаюсь вызвать другую функцию из своего адаптера просмотра ресайклера, я добавляю прослушиватель onclick в свой holder.itemView. Я пробовал setOnClickListener и onClick в своей деятельности с this@MainActivity в качестве параметра context, он отлично работает.

btn.setOnClickListener { showDialog(this@MainActivity) }
btn.onClick { showDialog(this@MainActivity) }

но onClick не будет работать в адаптере, потому что

holder.itemView.setOnClickListener {
    showDialog(context, notes[position])
} // This works fine

// Type mismatch required Context, Found CoroutineContext
holder.itemView.onClick { showDialog(context, notes[position]) }

Что мне делать, чтобы исправить это, если я хочу использовать onClick вместо setOnClickListener

откуда вы берете контекст, который вы передаете в случае holder.itemView.onClick {showDialog (context, notes [position])}?

Wajid 10.07.2018 13:05

Я получаю контекст из конструктора в моем адаптере class NotesAdapter(private val context: Context) : RecyclerView.Adapter<NotesAdapter.NotesViewHolder>() {

Fadel Trivandi Dipantara 10.07.2018 13:33
1
2
539
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Может попробовать это:

class NotesAdapter(private val ctx: Context) : RecyclerView.Adapter<NotesAdapter.NotesViewHolder>() {
    // Etc
    holder.itemView.onClick { showDialog(ctx, notes[position]) }
}

РЕДАКТИРОВАТЬ - Объяснение

Я ни в коем случае не эксперт в Kotlin, но полученная вами ошибка была очень ясным ключом к пониманию того, что происходит.

Когда вы вызываете holder.itemView.onClick под капотом, вы вызываете itemView.setOnClickListener, который принимает экземпляр View.OnClickListener. Итак, вы могли бы сделать что-то подобное, и это, вероятно, сработало бы нормально:

class NotesAdapter(private val context: Context) : RecyclerView.Adapter<NotesAdapter.NotesViewHolder>() {
    // Etc
    holder.itemView.onClick(View.OnClickListener(){
        void onClick(v: View) {
            showDialog(context, notes[position])
        }
    })
}

Вместо этого вы хотели использовать чистый синтаксис Kotlins и передать ему лямбду. Что совершенно верно и намного чище. Однако похоже, что лямбда (или сопрограмма), по-видимому, также имеет поле с именем context и имеет тип CoroutineContext. Продолжая приведенный выше пример, это эквивалент этого:

holder.itemView.onClick(View.OnClickListener(){
    var context: CoroutineContext
    void onClick(v: View) {
        showDialog(context, notes[position])
    }
})

В этом случае, когда вы вызываете showDialog, вы получаете «контекст» текущей области, которая является неправильным типом, поэтому вы получили ошибку несоответствия типа.

В java есть другое решение, я просто не знаю эквивалентного синтаксиса Kotlin. Вы бы сделали что-то вроде этого:

holder.itemView.onClick { showDialog(NotesAdapter.this.context, notes[position]) }

Это просто еще один способ сообщить компилятору, что контекст, который вы ищете, находится в области NotesAdapter, а не в области Coroutine.

Вы можете объяснить, почему этот подход работает?

Fadel Trivandi Dipantara 11.07.2018 05:43

Другие вопросы по теме