【问题标题】:Cannot access var object of inner class in kotlin无法在kotlin中访问内部类的var对象
【发布时间】:2018-10-19 05:14:12
【问题描述】:

我正在尝试在 Kotlin 中为 android 编写一个 RecyclerView 适配器类。我正在尝试使用为自定义对象创建自定义查看器类的传统方式,并在其中使用单击侦听器。虽然我可以做其余的事情,比如访问内部类的变量并显示 RecyclerView,但我无法将点击监听器添加到内部类的 var 对象中。

比如

 var convertView : View? = itemView

convertView.setOnClickListener(this)

以下是我完整的适配器类代码

public open class TestAdapter(val items: MutableList<Any>, val context: Activity) : RecyclerView.Adapter<TestAdapter.CustomViewHolder>() {

public var mItem: MutableList<Any> = items
public var mActivity: Activity = context
protected var clickListener: ExampleInterface? = null
public interface ExampleInterface {

    fun click(pos: Int) {

    }
}


open public fun setListener(mInterFaceListener: ExampleInterface) {
    clickListener = mInterFaceListener
}

override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CustomViewHolder {
    var parentLayout: View = LayoutInflater.from(mActivity).inflate(R.layout.custom_view, p0, false)
    return CustomViewHolder(parentLayout)

    //  return CustomViewHolder(LayoutInflater.from(mActivity).inflate(R.layout.custom_view, p0, false))
}

override fun getItemCount(): Int {
    return mItem.size
    TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun onBindViewHolder(p0: CustomViewHolder, p1: Int) {

    p0.dataView.text = mItem.get(p1).toString()

}

inner class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
    var convertView: View? = itemView
    var dataView: TextView = convertView!!.findViewById(R.id.data)

    var mposition = adapterPosition

    override fun onClick(p0: View?) {

        if (clickListener != null) {
            clickListener!!.click(mposition)
        }
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

}

所以如果你在 CustomView 类中看到这两行

var convertView: View? = itemView
    var dataView: TextView = convertView!!.findViewById(R.id.data)

我无法访问这些变量“convertView”和“dataView”,因此我可以为它们设置 clicklistener。那么如何实现呢? 谢谢:)

【问题讨论】:

    标签: android kotlin android-recyclerview


    【解决方案1】:

    我参考了这个网站

    https://www.raywenderlich.com/367-android-recyclerview-tutorial-with-kotlin

    在这里我知道我的错误,我需要在类中使用 init,在那里我可以访问它并在点击侦听器上进行初始化。搞定了

       init {
                convertView?.setOnClickListener(this)
            }
    

    虽然上述答案也可以接受,但由于我是 Kotlin 的新手,我不能说哪个是更好的选择,但我对上述网站的要求很满意。

    谢谢你:)

    【讨论】:

      【解决方案2】:

      RecyclerView 适配器中,您可以将OnClickListeners 放在onCreateViewHolder 中,以防止每次调用onBindViewHolder 时都设置它们(因为滚动RecyclerView 时会多次调用onBindViewHolder )。在您的onCreateViewHolder 中使用parentLayout 访问您的视图并将onClickListener 设置为它们。要确定onCreateViewHolder 中的当前位置,您可以执行以下操作:

      override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CustomViewHolder {
          val parentLayout: View = LayoutInflater.from(mActivity).inflate(R.layout.custom_view, p0, false)
          
          val customViewHolder = CustomViewHolder(parentLayout)
          parentLayout.myExampleTextView.setOnClickListener {
              // Place onClick logic here.
      
              // If you need position, do as bellow :
              val adapterPosition = customViewHolder.adapterPosition
              if(adapterPosition != RecyclerView.NO_POSITION) {
                  // Place your position dependent logic here
              }
          }
          
          return customViewHolder
      }
      

      更新: 我更新了上面的代码 sn-p 并添加了RecyclerView.NO_POSITION(等于-1)检查。位置返回为-1的原因解释如下。

      来自安卓文档:

      另外一组位置相关方法的形式为 适配器位置。 (例如 getAdapterPosition(), findViewHolderForAdapterPosition(int)) 你应该使用这些方法 当您需要使用最新的适配器位置时,即使它们 可能尚未反映到布局中。例如,如果你想 在 ViewHolder 单击时访问适配器中的项目,您应该使用 获取适配器位置()。请注意,这些方法可能无法 如果 notifyDataSetChanged() 已被调用,则计算适配器位置 新的布局还没有计算出来。由于这个原因,你 应该小心处理来自这些的 NO_POSITION 或 null 结果 方法。

      【讨论】:

      • 嘿,你能告诉我在哪里写这个代码的位置 var adapterPosition = viewHolder.adapterPosition Coz in onCreateViewHolder 我得到它是-1
      • 应该在 bindViewHolder 中而不是在 onCreateViewHolder 中??
      • @Pritish 我更新了答案,返回的 -1 用 if 语句解释和处理,应该处理以避免任何问题。至于为什么要把onClickListener放在onCreateViewHolder里,看看这个答案:stackoverflow.com/a/33845918/8551764
      • 实际上,最好将该代码放入 CustomViewHolder 的构造函数中。
      【解决方案3】:

      您可以在onBindViewHolder 中使用p0 这种方式p0.dataView 访问它们,这样您就可以成功设置监听器

      【讨论】:

      • 是的,但这是正确的做法吗?由于绑定持有者专门用于设置数据,并且它将在每次绑定时继续设置侦听器。这不是我们过去在 Java 中传统的自定义视图类中这样做的原因吗?
      • N 想法,我用这种方式,它总是有效,从未遇到任何问题@Pritish
      • 所以你为每个变量单独编写它,例如 p0.dataView.setOnClickListener(View.OnClickListener { }) p0.dataView1.setOnClickListener(View.OnClickListener { })
      • 不,我没有,它为所有(dataView)生成监听器,您可以使用 p1 获取每个视图的位置并自定义添加监听器@Pritish
      猜你喜欢
      • 2018-03-04
      • 1970-01-01
      • 2017-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      相关资源
      最近更新 更多