Нет доступа к просмотру в держателе - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь создать RecyclerView адаптер и следую этой документации.

private class Adapter(private val list: List<HashMap<String, Any>>, private val ctx: Context) : RecyclerView.Adapter<Adapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {
        var mTextView: TextView

        return ViewHolder(ctx.UI {
            relativeLayout {
                mTextView = textView("1 + 1 = 2")
            }
        }.view)
    }

    override fun getItemCount() = list.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.mTextView.text = "1 + 1 = 3" // Should work?
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
}

Как мне получить доступ к mTextView в onBindViewHolder?

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Что вам нужно сделать здесь, это создать свойство для вашего TextView внутри вашего ViewHolder. Это не особенно легко с Анко, но вот несколько способов сделать это.


1. Передайте каждый View, на который вы хотите ссылаться из вашего ViewHolder, как отдельный параметр конструктора.

Для этого решения вы должны изменить класс ViewHolder следующим образом, добавив свойство для TextView:

class ViewHolder(view: View, val mTextView: TextView) : RecyclerView.ViewHolder(view)

Вы можете инициализировать это свойство немного запутанным способом:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {
    lateinit var mTextView: TextView

    val view = ctx.UI {
        relativeLayout {
            mTextView = textView("1 + 1 = 2")
        }
    }.view

    return ViewHolder(view, mTextView)
}

Хотя это выглядит не очень хорошо, вы сохраняете ссылку на ваш TextView с момента его первоначального создания, поэтому он эффективен.


2. Присвойте созданные Anko View идентификаторы экземпляров и найдите их по их идентификаторам позже.

Во-первых, вы должны создать константы для своих идентификаторов - идентификатор может быть любым положительным числом, просто убедитесь, что они уникальны в пределах области, в которой вы их используете. Один из способов - разместить их внутри объекта-компаньона, например:

companion object {
    private const val TEXT_VIEW_ID = 123 // Arbitrary positive number
}

Затем вам нужно присвоить этот идентификатор вашему TextView:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {
    return ViewHolder(ctx.UI {
        relativeLayout {
            textView("1 + 1 = 2") {
                id = TEXT_VIEW_ID
            }
        }
    }.view)
}

Наконец, вы можете снова найти ваш TextView в вашем классе ViewHolder с findViewById:

class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    val mTextView: TextView = view.findViewById(TEXT_VIEW_ID)
}

Конечно, это будет медленнее, потому что вы теряете ссылку TextView, которая была у вас, когда вы передавали View на ViewHolder, а затем вы снова ее просматривали .


Обратите внимание, что я набрал mTextView для ответа, чтобы было легче следовать, но обычно не рекомендуется использовать венгерскую нотацию или любые другие префиксы имен в Kotlin.

0 голосов
/ 01 мая 2018

Если вы используете расширения kotlin и имеете текстовое представление с идентификатором mTextView, то оно должно быть:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.itemView.mTextView.text = "1 + 1 = 3" // Should work?
    }

Вы также можете определять переменные в вашем ViewHolder и использовать их напрямую, это лучший способ с точки зрения производительности, поскольку он не будет вызывать ненужных вызовов findviewbyid :

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val myTextView = itemView.mTextView
}

И позже доступ к нему, как:

 holder.myTextView.text = "some text"
...