回收器查看多个视图持有者项目详细信息查找



我的回收视图(用于聊天视图(正确加载视图,但是当我点击视图时,它会引发投射异常:

ViewHolderReceived cannot be cast to ViewHolderSent

查看者:

class ViewHolderReceived(val view: View) : RecyclerView.ViewHolder(view) {
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition(): Int = adapterPosition
override fun getSelectionKey(): Long? = itemId
override fun inSelectionHotspot(e: MotionEvent): Boolean {
return true
}
}
fun bind(isSelected: Boolean = false) {
itemView.isSelected = isSelected
}
}
//#########################################################################
class ViewHolderSent(val view: View) : RecyclerView.ViewHolder(view) {
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition(): Int = adapterPosition
override fun getSelectionKey(): Long? = itemId
override fun inSelectionHotspot(e: MotionEvent): Boolean {
return true
}
}
fun bind(isSelected: Boolean = false) {
itemView.isSelected = isSelected
}
}

项目详细信息查找:

class MyItemDetailsLookup(private val recyclerView: RecyclerView) :
ItemDetailsLookup<Long>() {
override fun getItemDetails(event: MotionEvent): ItemDetails<Long>? {
val view = recyclerView.findChildViewUnder(event.x, event.y)
if (view != null) {
return if(recyclerView.getChildAdapterPosition(view) == 0){
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderReceived)
.getItemDetails()} else {
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderSent)
.getItemDetails()} // error here
}
return null
}
}

无论点击哪个视图,它都会抛出相同的错误(对于 ViewHolderReceived 或 ViewHolderSent(,但会以正确的顺序正确绑定它们。

注意:如果我在点击任何发送的视图后点击收到的视图,它只会引发错误,反之亦然

找到解决方案:问题是recyclerView.getChildAdapterPosition(愚蠢的我,半睡半醒地写的(。

如果您将共享方法提取到超类或接口,则可以轻松解决此问题,然后无论如何您都可以执行安全转换。例如:

abstract class SelectableViewHolder(val view: View) : RecyclerView.ViewHolder(view){
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition(): Int = adapterPosition
override fun getSelectionKey(): Long? = itemId
override fun inSelectionHotspot(e: MotionEvent): Boolean {
return true
}
}
open fun bind(isSelected: Boolean = false) {
itemView.isSelected = isSelected
}
}
class ViewHolderReceived(view: View) : SelectableViewHolder(view) {
override fun bind(isSelected: Boolean = false) {
super.bind(isSelected)
// anything else specific for received viewholder
}
}
class ViewHolderSent(view: View) : SelectableViewHolder(view) {
override fun bind(isSelected: Boolean = false) {
super.bind(isSelected)
// anything else specific for sent viewholder
}
}

然后查找很容易:

class MyItemDetailsLookup(private val recyclerView: RecyclerView) : ItemDetailsLookup<Long>() {
override fun getItemDetails(event: MotionEvent): ItemDetails<Long>? {
return recyclerView.findChildViewUnder(event.x, event.y)?.let {
(recyclerView.getChildViewHolder(it) as SelectableViewHolder).getItemDetails()
}
}
}
return if(recyclerView.getChildAdapterPosition(view) == 0){
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderReceived)
.getItemDetails()} else {
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderSent)
.getItemDetails()} // error here

您假设该位置肯定返回您要转换到的值。当你做SomeValue as SomeType你断言SomeValue肯定是SomeType的继承者。

如果您不知道是这种情况,在这种情况下您不知道,因为您可以投射到两种可能的类型。在强制转换类型之前,必须检查类型是否is特定类型。

如果不是,您将收到错误,指出您正在cannot cast x to y

您应该使用

if(recyclerView.getChildAdapterPosition(view) == 0){
if (recyclerView.getChildViewHolder(view) is MyAdapter.ViewHolderReceived) {
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderReceived).getItemDetails()
} else {
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderSent).getItemDetails()
(recyclerView.getChildViewHolder(view).getItemDetails
} 
}

最新更新