【问题标题】:OnClickListener is not working inside my adapter classOnClickListener 在我的适配器类中不起作用
【发布时间】:2021-04-07 19:48:30
【问题描述】:

我查看了许多在线发布的解决方案,但它们无法解决我的问题。可能适配器位置返回 -1,但为什么呢?

    java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
        at java.util.ArrayList.get(ArrayList.java:439)
        at 
    com.firebase.ui.common.BaseObservableSnapshotArray.getSnapshot(BaseObservableSnapshotArray.java:70)
        at com.example.twitterclone.adapters.MyAdapter$TweetViewHolder.<init>(MyAdapter.kt:36)
        at com.example.twitterclone.adapters.MyAdapter.onCreateViewHolder(MyAdapter.kt:50)
        at com.example.twitterclone.adapters.MyAdapter.onCreateViewHolder(MyAdapter.kt:21)
        at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078)
        at 

RecyclerViewAdapterCode:

    class MyAdapter(
    options: FirestoreRecyclerOptions<Tweet>,
    private val clickInterface: ClickInterface
    ):FirestoreRecyclerAdapter<Tweet, MyAdapter.TweetViewHolder>(options) {

    inner class TweetViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val profile =
            view.findViewById<de.hdodenhof.circleimageview.CircleImageView>(R.id.userProfile)
        val tweet = view.findViewById<TextView>(R.id.tweet)
        val like = view.findViewById<TextView>(R.id.totalLikes)
        val thumbsUp = view.findViewById<ImageView>(R.id.thumbsUp)
        val name=view.findViewById<TextView>(R.id.tweetUserName)
        init {


                val tweetId=snapshots.getSnapshot(adapterPosition).get("tweetId")
                thumbsUp.setOnClickListener {
                    clickInterface.clickLike(tweetId.toString())
                }

        }


    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): TweetViewHolder {
        val viewHolder = TweetViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.post_tweets_item, parent, false)
        )



        return viewHolder
    }

    override fun onBindViewHolder(
        holder: TweetViewHolder,
        position: Int,
        model: Tweet
    ) {
        holder.tweet.text = model.content.toString()
        holder.like.text = model.likes.toString()
        UserDao().getUser(model.uid!!).get().addOnSuccessListener {
            holder.name.text = it.get("name").toString()
            Glide.with(holder.profile.context).load(it.get("profileUrl").toString())
                .into(holder.profile)
        }


    }
     }

布局代码

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_margin="10dp"
    android:layout_height="wrap_content">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="2dp"
        app:cardCornerRadius="5dp"
        app:cardElevation="2dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <de.hdodenhof.circleimageview.CircleImageView
                    android:id="@+id/userProfile"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_marginTop="8dp"
                    android:layout_marginLeft="8dp" />

                <TextView
                    android:id="@+id/tweetUserName"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:textColor="@android:color/black"
                    android:layout_marginTop="8dp" />
            </LinearLayout>

            <TextView
                android:id="@+id/tweet"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="13dp"
                android:textColor="@android:color/black" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="80dp"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:layout_width="30dp"
                        android:id="@+id/thumbsUp"
                        android:clickable="true"
                        android:layout_height="30dp"
                        android:src="@drawable/ic_baseline_thumb_up_24" />

                    <TextView
                        android:id="@+id/totalLikes"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center" />
                </LinearLayout>

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="80dp"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:clickable="true"
                        android:layout_width="30dp"
                        android:layout_height="30dp"
                        android:id="@+id/comments"
                        android:src="@drawable/ic_baseline_comment_24" />

                    <TextView
                        android:id="@+id/totalComments"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center" />
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </androidx.cardview.widget.CardView>

</LinearLayout>

【问题讨论】:

  • 尝试在onClickListener 中设置断点,看看它是否真的触发了onClick?

标签: android kotlin android-recyclerview firebaseui


【解决方案1】:

ViewHolder 的 init 块中的adapterPosition 返回 -1。所以我们只需要在监听器中调用adapterPosition 就可以解决这个问题,因为它会在创建视图持有者并附加到recyclerview 时检索位置。在 init 块中设置任何类型的侦听器都是一种好方法,因为 onCreateViewHolder 仅调用一次以创建视图持有者,但 onBindViewHolder 为同一个视图持有者调用多次,因此在 onBindViewHolder 中设置侦听器将是多余的。

   init {

            thumbsUp.setOnClickListener {
                val tweetId=snapshots.getSnapshot(adapterPosition).get("tweetId")
                clickInterface.clickLike(tweetId.toString())
            }

   }

【讨论】:

    【解决方案2】:

    在onBindViewHolder中附加你的onClickListener

    override fun onBindViewHolder(
                holder: TweetViewHolder,
                position: Int,
                model: Tweet
            ) {
                //your code of attaching data to view
                holder.thumbsUp.setOnClickListener{
                  clickInterface.clickLike(model.tweetId.toString())
               }
             }
    

    重新考虑您的应用架构。由于在 RecyclerView.Adapter 中向 DAO 询问数据是一种很奇怪的方法

    【讨论】:

    • 不,不要那样做。在 onbindviewholder 中附加监听器很糟糕,因为这会对性能产生很大影响!
    • 添加点击列表对性能有影响吗?关于什么?
    • 当然是在 recyclerview 上。 OnBindViewHolder() 将被多次调用,因此监听器也将被多次附加。永远不要这样做,而应将侦听器附加到OnCreateViewHolder()
    • 对不起,但是哈哈哈。在 onBindViewHolder 中调用一次 setOnClickListener 时出现很大的性能问题。并且作为对作者为 onBindViewHolder 中的数据调用 DAO 的代码的注释。在这个特定的示例中,更不知道什么更好,因为我们不知道作者使用方法 snapshots.getSnapshot(adapterPosition).get("tweetId") 做了什么。而且我认为在每次绑定时调用 setOnClickListener 是更大的性能问题:P
    • 嗯,你的部分答案是正确的。但是仅仅因为作者在他的 onBindViewHolder 中做了可怕的事情,你不必做同样的事情:P
    【解决方案3】:

    是的,我希望 ViewHolder 的 init 块中的 getSnapshotcall 中的 adapterPosition 返回 -1。据我所知,all the adapter position getters return the position of the last requested item for display. 但是当你第一次创建ViewHolders 时,还没有任何东西绑定到适配器(它仍然处于设置阶段),所以它的默认position 可能是 -1.

    基本上RecyclerViews 的工作方式是这样的——你定义这些ViewHolder 对象,它们基本上是显示每个项目数据的东西。适配器不是为列表中的每个项目创建一个,而是创建一些(足以填充可见区域和两侧的一对),然后通过移动它们来回收它们'重新消失,并更新其内容以表示不同的项目。

    onCreateViewHolder 是适配器调用以创建这些容器对象。在这里您可以扩展布局并通常在视图上执行findViewById,以便您可以引用它们,并且您可以设置TextView 的文本,而不必每次要更新视图时都必须找到视图。

    onBindViewHolder 是当您需要使用不同项目的信息更新 ViewHolder 时调用的名称。在这里,您实际上可以进行所有数据设置、更改图像等操作,并在必要时更新点击侦听器。

    基本上你不应该在ViewHolderinit 块中使用adapterPosition,因为在构造对象时会调用一次。那时您不仅没有有意义的职位,而且随着职位的变化,您不希望经常更新吗?这就是onBindViewHolder 的用途!它有传入的位置和一切。这就是你设置状态的方法

    【讨论】:

      猜你喜欢
      • 2021-04-21
      • 1970-01-01
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      相关资源
      最近更新 更多