ViewHolder 不能转换为 OtherViewHolder

ViewHolder cannot be cast to OtherViewHolder

我的 Recyclerview 自定义适配器有问题。 我试图在一个回收站视图中显示两个具有不同数据源的不同视图。 在我进行一些更改之前它运行良好,但现在出现异常。

它工作正常,直到 notifyDataSetChanged() 函数! holder.txtDelete.onClick 或 holder.txtEdit.onClick 函数触发时会发生崩溃!

我搜索了很多但找不到解决方案。感谢您的帮助

我的自定义适配器:

import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.os.Vibrator
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import artemis.team.picandtext.*
import com.squareup.picasso.Picasso
import org.jetbrains.anko.alert
import org.jetbrains.anko.sdk27.coroutines.onClick
import java.util.*

class RecAdapter(
    context: Context,
    activity: Activity,
    grplist: MutableList<GrpsValues> = mutableListOf(),
    itemslist: MutableList<ItemsValues> = mutableListOf()
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private var context: Context? = null
    private var activity: Activity? = null
    private var grpList = mutableListOf<GrpsValues>()
    private var itemsList = mutableListOf<ItemsValues>()
    private lateinit var tts: TextToSpeech
    private var voiceText = "Text not found!"
    private var voiceLocale = "en-US"
    private var mode = 0
    private var itemsSize = 0
    private var groupsSize = 0
    private val ITEM = 100
    private val GROUP = 200
    private var HOLDER = GROUP

    init {
        this.activity = activity
        this.context = context
        this.grpList = grplist
        this.itemsList = itemslist
        itemsSize = itemsList.size
        groupsSize = grpList.size
    }

    override fun getItemCount(): Int {
        return (itemsList.size + grpList.size)
    } // getItemCount

    override fun onBindViewHolder(recHolder: RecyclerView.ViewHolder, pos: Int) {

        Mode()

        if (mode == ITEM && HOLDER == ITEM) {

            val holder = recHolder as ItemsViewHolder

            if (itemsList.size > 0) {
                val position = pos - grpList.size

                Picasso.get()
                    .load(itemsList[position].url)
                    .error(R.drawable.empty)
                    .into(holder.image)

                holder.title.text = itemsList[position].title
                holder.txtID.text = itemsList[position].id
                holder.grpID.text = itemsList[position].grpID

                val grpID = holder.grpID.text.toString()

                lateinit var dialog: DialogInterface

                holder.layout.onClick {
                    (context!!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator?)!!.vibrate(30)
                    dialog = context!!.alert {
                        val view = activity!!.layoutInflater.inflate(R.layout.dialog_item_details, null)
                        val prgDatabase = PrgDatabase(context)
                        val value = prgDatabase.ItemsFind(holder.txtID.text.toString())
                        view.findViewById<TextView>(R.id.TxtText).text = value.title
                        Picasso.get()
                            .load(value.url)
                            .error(R.drawable.empty)
                            .into(view.findViewById<ImageView>(R.id.imageView))

                        customView = view
                    }.show()
                }

                holder.txtDelete.onClick {
                    (context!!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator?)!!.vibrate(30)
                    context!!.alert {
                        title = "ItemsDelete"
                        message = "ItemsDelete item from the list?"

                        positiveButton("Yup") {
                            val prgDatabase = PrgDatabase(context)
                            prgDatabase.ItemsDelete(holder.txtID.text.toString())
                            itemsList = PrgDatabase(context).ItemsGetAll(grpID)

                            this@RecAdapter.notifyDataSetChanged()

                            it.dismiss()
                        }

                        negativeButton("NO") {
                            it.dismiss()
                        }

                    }.show()
                }

                holder.txtEdit.onClick {
                    (context!!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator?)!!.vibrate(30)

                    dialog = context!!.alert {
                        val view = activity!!.layoutInflater.inflate(R.layout.dialog_items, null)
                        view.findViewById<Button>(R.id.BTNsaveID).text = "Save changes"
                        val prgDatabase = PrgDatabase(context)

                        val adapter = ArrayAdapter<String>(
                            context!!,
                            android.R.layout.simple_spinner_item,
                            context!!.resources.getStringArray(
                                R.array.langueges
                            )
                        )
                        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
                        view.findViewById<Spinner>(R.id.SpLangsID).adapter = adapter

                        val value = prgDatabase.ItemsFind(holder.txtID.text.toString())
                        view.findViewById<EditText>(R.id.ETtitleID).setText(value.title)
                        view.findViewById<EditText>(R.id.ETurlID).setText(value.url)
                        view.findViewById<Spinner>(R.id.SpLangsID).setSelection(
                            when (value.local) {
                                "English" -> 0
                                "Russian" -> 1
                                "Turkish" -> 2
                                "French" -> 3
                                "German" -> 4
                                "Italian" -> 5
                                "Korean" -> 6
                                else -> 0
                            }
                        )
                        view.findViewById<Button>(R.id.BTNsaveID).onClick {
                            if (view.findViewById<EditText>(R.id.ETtitleID).text.isNotEmpty()
                                && view.findViewById<EditText>(R.id.ETurlID).text.isNotEmpty()
                            ) {
                                val value = ItemsValues(
                                    title = view.findViewById<EditText>(R.id.ETtitleID).text.toString(),
                                    url = view.findViewById<EditText>(R.id.ETurlID).text.toString(),
                                    id = holder.txtID.text.toString(),
                                    grpID = grpID,
                                    local = view.findViewById<Spinner>(R.id.SpLangsID).selectedItem.toString()
                                )
                                prgDatabase.ItemsUpdate(
                                    value
                                )
                                itemsList[position] = value
                                dialog.dismiss()


                                this@RecAdapter.notifyDataSetChanged()
                                this@RecAdapter.notifyItemChanged(position)


                            }// if
                        } // btn on click
                        customView = view

                    }.show()
                } // on click
            }

        } // if Items
        else if (mode == GROUP && HOLDER == GROUP) {

            val holder = recHolder as GrpsViewHolder
            if (grpList.size > 0) {

                val position = pos

                holder.titleGrp.text = grpList[position].title

                holder.txtItemIDGrp.text = grpList[position].id
                holder.txtParentGrpIDGrp.text = grpList[position].parent

                holder.layoutGrp.onClick {
                    val intent = Intent(context, MainActivity::class.java)
                    intent.putExtra("GrpID", holder.txtItemIDGrp.text.toString())
                    intent.putExtra("GrpTitle", grpList[position].title)
                    activity!!.startActivity(intent)
                }

                holder.txtDeleteGrp.onClick {
                    (context!!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator?)!!.vibrate(30)
                    context!!.alert {
                        title = "Delete"
                        message = """
                        Delete Group from the list?

                        * With delete this group, all it's words and pictures will be removed!
                        """.trimIndent()

                        positiveButton("Yup") {
                            val prgDatabase = PrgDatabase(context)
                            prgDatabase.GrpsDelete(holder.txtItemIDGrp.text.toString())

                            grpList = PrgDatabase(context).GrpsGetAll(grpList[position].parent)

                            this@RecAdapter.notifyItemRemoved(position)
                            this@RecAdapter.notifyDataSetChanged()

                            it.dismiss()
                        }

                        negativeButton("NO") {
                            it.dismiss()
                        }

                    }.show()
                }

                lateinit var dialog: DialogInterface
                holder.txtEditGrp.onClick {
                    (context!!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator?)!!.vibrate(30)

                    dialog = context!!.alert {
                        val view = activity!!.layoutInflater.inflate(R.layout.dialog_grps, null)

                        view.findViewById<Button>(R.id.BTNsaveID).text = "Save changes"
                        val prgDatabase = PrgDatabase(context)
                        val value = prgDatabase.GrpsFind(holder.txtItemIDGrp.text.toString())
                        view.findViewById<EditText>(R.id.ETtitleID).setText(value.title)
                        view.findViewById<Button>(R.id.BTNsaveID).onClick {
                            if (view.findViewById<EditText>(R.id.ETtitleID).text.isNotEmpty()) {
                                val value = GrpsValues(
                                    title = view.findViewById<EditText>(R.id.ETtitleID).text.toString(),
                                    id = holder.txtItemIDGrp.text.toString(),
                                    parent = holder.txtParentGrpIDGrp.text.toString()
                                )
                                prgDatabase.GrpsUpdate(
                                    value
                                )
                                grpList[position] = value
                                dialog.dismiss()

                                this@RecAdapter.notifyDataSetChanged()
                                this@RecAdapter.notifyItemChanged(position)

                            }// if
                        } // btn on click
                        customView = view
                    }.show()
                } // on click
            } // if
        } // GROUP

    } // onBindViewHolder

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        if (groupsSize > 0) {
            HOLDER = GROUP
            return GrpsViewHolder(
                LayoutInflater.from(parent.context).inflate(
                    R.layout.custom_rec_grps_layout,
                    parent,
                    false
                )
            )

        } else {
            HOLDER = ITEM
            return ItemsViewHolder(
                LayoutInflater.from(parent.context).inflate(
                    R.layout.custom_rec_items_layout,
                    parent,
                    false
                )
            )
        }
    }

    inner class ItemsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val image: ImageView = view.findViewById(R.id.imageView)
        val title: TextView = view.findViewById(R.id.TxtText)
        val txtID: TextView = view.findViewById(R.id.TxtItemID)
        val grpID: TextView = view.findViewById(R.id.TxtGrpID)
        val txtDelete: TextView = view.findViewById(R.id.TxtDeleteID)
        val txtEdit: TextView = view.findViewById(R.id.TxtEditID)
        val layout: CardView = view.findViewById(R.id.ConstItemsID)
    }

    inner class GrpsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val titleGrp: TextView = view.findViewById(R.id.GrpTxtText)
        val txtItemIDGrp: TextView = view.findViewById(R.id.GrpTxtItemID)
        val txtParentGrpIDGrp: TextView = view.findViewById(R.id.GrpTxtGrpID)
        val txtDeleteGrp: TextView = view.findViewById(R.id.GrpTxtDeleteID)
        val txtEditGrp: TextView = view.findViewById(R.id.GrpTxtEditID)
        val layoutGrp: CardView = view.findViewById(R.id.CnstGrpsID)

    }

    override fun getItemViewType(position: Int): Int {
        return position
    }


    fun Mode() {
        if (groupsSize > 0) {
            groupsSize--
            mode = GROUP
        } else if (itemsSize > 0) {
            itemsSize--
            mode = ITEM
        }
    }
}

这是 logcat 错误:

   --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: artemis.team.picandtext, PID: 18621
    java.lang.ClassCastException: GrpsViewHolder cannot be cast to RecAdapter$ItemsViewHolder
       enter code here at RecAdapter.onBindViewHolder(RecAdapter.kt:66)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
        at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:557)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
        at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:171)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
        at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3336)
        at android.view.View.measure(View.java:22071)
        at androidx.constraintlayout.widget.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227)
        at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1572)
        at android.view.View.measure(View.java:22071)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:22071)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
        at android.view.View.measure(View.java:22071)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:22071)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
        at android.view.View.measure(View.java:22071)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:724)
        at android.view.View.measure(View.java:22071)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2422)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1504)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1761)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
        at android.view.Choreographer.doCallbacks(Choreographer.java:723)
        at android.view.Choreographer.doFrame(Choreographer.java:658)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)


    --------- beginning of system

您不能将 ViewHolder 类型的一个子类型转换为另一种类型的 ViewHolder class,因为它们不是同一类型。

    ViewHolder
       /\
RecHolder ItemsViewHolder

A RecHolder 一个ViewHolder,而ItemsViewHolder是一个viewholder,但仅仅因为它们共享同一个父对象并不能构成RecHolder 一个 ItemsViewHolder 所以演员永远不会成功。

检查您的逻辑以确定您的 onCreateViewHolder returns 的 ViewHolder 是什么,因为这是进入您的 onBindViewHolder

ViewHolder 类型

如果你想要一种在你的逻辑内部进行双重检查的方法,在你施放每个之前做 if (viewHolder is RecHolder)if(viewHolder is ItemViewHolder) 来验证你得到了你认为你的那个'重新获得。