OnClickListener 在我的适配器中不工作 class
OnClickListener is not working inside my adapter class
看了很多网上的解决方案,都不能解决我的问题。适配器位置可能返回 -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>
在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())
}
}
重新考虑您的应用程序架构。因为向 DAO 询问 RecyclerView.Adapter 中的数据是一种很奇怪的方法
是的,我希望您在 ViewHolder
的初始化块中的 getSnapshot
调用中的 adapterPosition
返回 -1。据我所知,all the adapter position getters return the position of the last requested item for display. 但是当你第一次创建 ViewHolder
s 时,还没有任何东西绑定到适配器(它仍然处于设置阶段),所以它的默认值 position
大概是 -1.
基本上 RecyclerView
的工作方式是这样的 - 您定义这些 ViewHolder
对象,这些对象基本上是显示每个项目的数据的东西。适配器没有为列表中的每个项目创建一个,而是创建了一些(足以填充可见区域和两边的一对),然后 通过移动它们来回收 它们当他们不在视野中时,更新他们的内容以代表不同的项目。
onCreateViewHolder
是适配器调用以创建那些容器对象的内容。在这里你可以膨胀布局并且通常在视图上做 findViewById
所以你有一个对它们的引用,你可以只设置一个 TextView
的文本而不是每次你想要的时候都必须找到视图更新它。
onBindViewHolder
是当您需要用不同项目的信息更新 ViewHolder
时调用的内容。这是您实际进行所有数据设置、更改图像等的地方,必要时更新点击侦听器。
基本上您不应该在 ViewHolder
的 init
块中使用 adapterPosition
,因为在构造对象时会调用一次。那时您不仅没有有意义的职位,而且随着职位的变化,您不希望经常更新吗?这就是 onBindViewHolder
的用途!它具有传入的位置和所有内容。那就是你设置 state
的方法
ViewHolder 的初始化块中的 adapterPosition
返回 -1。所以我们只需要在侦听器中调用 adapterPosition
即可解决问题,因为它会在创建视图持有者并将其附加到 recyclerview
时检索位置。在 init 块中设置任何类型的侦听器是一个很好的方法,因为 onCreateViewHolder
只调用一次来创建一个视图持有者,而 onBindViewHolder
为同一个视图持有者调用多次,所以在 onBindViewHolder
是多余的。
init {
thumbsUp.setOnClickListener {
val tweetId=snapshots.getSnapshot(adapterPosition).get("tweetId")
clickInterface.clickLike(tweetId.toString())
}
}
看了很多网上的解决方案,都不能解决我的问题。适配器位置可能返回 -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>
在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())
}
}
重新考虑您的应用程序架构。因为向 DAO 询问 RecyclerView.Adapter 中的数据是一种很奇怪的方法
是的,我希望您在 ViewHolder
的初始化块中的 getSnapshot
调用中的 adapterPosition
返回 -1。据我所知,all the adapter position getters return the position of the last requested item for display. 但是当你第一次创建 ViewHolder
s 时,还没有任何东西绑定到适配器(它仍然处于设置阶段),所以它的默认值 position
大概是 -1.
基本上 RecyclerView
的工作方式是这样的 - 您定义这些 ViewHolder
对象,这些对象基本上是显示每个项目的数据的东西。适配器没有为列表中的每个项目创建一个,而是创建了一些(足以填充可见区域和两边的一对),然后 通过移动它们来回收 它们当他们不在视野中时,更新他们的内容以代表不同的项目。
onCreateViewHolder
是适配器调用以创建那些容器对象的内容。在这里你可以膨胀布局并且通常在视图上做 findViewById
所以你有一个对它们的引用,你可以只设置一个 TextView
的文本而不是每次你想要的时候都必须找到视图更新它。
onBindViewHolder
是当您需要用不同项目的信息更新 ViewHolder
时调用的内容。这是您实际进行所有数据设置、更改图像等的地方,必要时更新点击侦听器。
基本上您不应该在 ViewHolder
的 init
块中使用 adapterPosition
,因为在构造对象时会调用一次。那时您不仅没有有意义的职位,而且随着职位的变化,您不希望经常更新吗?这就是 onBindViewHolder
的用途!它具有传入的位置和所有内容。那就是你设置 state
adapterPosition
返回 -1。所以我们只需要在侦听器中调用 adapterPosition
即可解决问题,因为它会在创建视图持有者并将其附加到 recyclerview
时检索位置。在 init 块中设置任何类型的侦听器是一个很好的方法,因为 onCreateViewHolder
只调用一次来创建一个视图持有者,而 onBindViewHolder
为同一个视图持有者调用多次,所以在 onBindViewHolder
是多余的。
init {
thumbsUp.setOnClickListener {
val tweetId=snapshots.getSnapshot(adapterPosition).get("tweetId")
clickInterface.clickLike(tweetId.toString())
}
}