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又正常了呢???有点不理解
15
收起
正在回答
1回答
如果是val callback=new Callback<String> 这种形式的编译时会被擦除
但如果是
class MyCallback implement Callback<String>{}
此时不会被擦除,你可以通过字节码来查看生成的产物。
所以goodsItemHolder 如果不继承HiViewHolder
那么父类GoodsItem里面就会报类型转换错误
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧