HiAapter.createViewHolderInternal类型转换异常

HiAapter.createViewHolderInternal类型转换异常

按视频说的已经改成return HiViewHoder

/**
     * 创建ViewHolder
     *
     * @return 如果是DataItem对象,返回父类的ViewHolder泛型参数,否则返回
     */
    private fun createViewHolderInternal(
        javaClass: Class<HiDataItem<*, out RecyclerView.ViewHolder>>,
        view: View
    ): RecyclerView.ViewHolder {
        //得到该Item的父类类型,即为HiDataItem.class。  class 也是type的一个子类。
        //type的子类常见的有 class,类泛型,ParameterizedType参数泛型 ,TypeVariable字段泛型
        //所以进一步判断它是不是参数泛型
        val superclass = javaClass.genericSuperclass
        if (superclass is ParameterizedType) {
            //得到它携带的泛型参数的数组
            val arguments = superclass.actualTypeArguments
            //挨个遍历判断 是不是咱们想要的 RecyclerView.ViewHolder 子类 类型的。
            for (argument in arguments) if (argument is Class<*>
                && RecyclerView.ViewHolder::class.java.isAssignableFrom(argument)
            ) {
                try {
                    //如果是,则使用反射 实例化类上标记的实际的泛型对象
                    //这里需要  try-catch 一把,如果咱们直接在HiDataItem子类上标记 RecyclerView.ViewHolder,抽象类是不允许反射的
                    return argument.getConstructor(View::class.java)
                        .newInstance(view) as RecyclerView.ViewHolder
                } catch (e: Throwable) {
                    e.printStackTrace()
                }
            }
        }
        return object : HiViewHolder(view) {}  
    }

课程源码是写成 onViewAttachedToWindow(holder: GoodsItemHolder)


private inner class ShopGoodsItem(goodsModel: GoodsModel) : GoodsItem(goodsModel, false) {

        override fun getItemLayoutRes(): Int {
            return R.layout.layout_detail_item_shop_goods_item
        }

        //override fun onViewAttachedToWindow(holder: GoodsItemHolder) { //错误代码
        override fun onViewAttachedToWindow(holder: HiViewHolder) {//正常代码
            super.onViewAttachedToWindow(holder)

            val viewParent: ViewGroup = holder.itemView.parent as ViewGroup
            val availableWidth =
                viewParent.measuredWidth - viewParent.paddingLeft - viewParent.paddingRight
            val itemWidth = availableWidth / SHOP_GOODS_ITEM_SPAN_COUNT
            val itemImage = holder.item_image
            val params = itemImage.layoutParams
            params.width = itemWidth
            params.height = itemWidth
            itemImage.layoutParams = params

        }

    }

GoodsItem里面的源码

open class GoodsItem(private val goodsModel: GoodsModel, private val hotTab: Boolean) :
    HiDataItem<GoodsModel, GoodsItem.GoodsItemHolder>(goodsModel) {//错误
    HiDataItem<GoodsModel, HiViewHolder>(goodsModel) {//正常
    //省略...
    
    class GoodsItemHolder(view: View) : HiViewHolder(view)

}

之前问过 class GoodsItemHolder(view: View) : HiViewHolder(view) 这种写法是为了方便DataBinding库使用的写法,但是如果按老师视频说的,GoodsItemHolder继承HiViewHolder,父类会被泛型擦除掉,那么会报类型转换异常,那么为什么源码的跑起来没问题,我自己写GoodsItemHolder有问题,但是改成HiViewHolder又正常了呢???有点不理解

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

如果是val  callback=new  Callback<String>  这种形式的编译时会被擦除
但如果是
class  MyCallback  implement Callback<String>{}
此时不会被擦除,你可以通过字节码来查看生成的产物。

所以goodsItemHolder  如果不继承HiViewHolder
那么父类GoodsItem里面就会报类型转换错误

  • 默小铭 提问者 #1
    老师好像没看到我上面的代码,class GoodsItemHolder(view: View) : HiViewHolder(view) 是这样写的,但编译出来还是类型转换异常 java.lang.ClassCastException: zs.xmx.hi.ui.item.HiAdapter$createViewHolderInternal$1 cannot be cast to zs.xmx.pub_mod.model.items.GoodsItem$GoodsItemHolder at zs.xmx.pub_mod.model.items.GoodsItem.onBindData(GoodsItem.kt:32) at zs.xmx.hi.ui.item.HiAdapter.onBindViewHolder(HiAdapter.kt:232)
    2020-10-25 18:22:05
  • LovelyChubby 回复 提问者 默小铭 #2
    这应该是泛型没有识别到,看下课程的代码怎么写的 HiAdapter.createViewHolderInternal$1 这个是new recyclerview. viewholder了。所以类型转换错误
    2020-10-26 10:31:22
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师
插入代码