如何在NexusAdapter类中运行时创建泛型TViewHolder类型对象
创建泛型TViewHolder实例的解决方案
这是个典型的泛型类型擦除问题——因为Kotlin的泛型信息在运行时会被擦除,所以你没法直接在NexusAdapter里用TViewHolder(itemView)这种方式创建实例。下面给你两种可行的方案,优先推荐第一种更安全、性能更好的实现:
方案1:使用工厂函数(推荐)
让子类通过工厂函数提供ViewHolder的创建逻辑,这种方式不需要反射,类型安全且性能无损耗。
修改抽象类代码
open abstract class NexusAdapter<TData: NexusIdProvider, TViewHolder: NexusViewHolder<TData>> ( protected val ctx: Context, private val _layoutId: Int, protected val items: List<TData>, // 添加一个工厂函数,用于创建ViewHolder实例 private val viewHolderFactory: (View) -> TViewHolder ): BaseAdapter() { override fun getView(position: Int, view: View?, parent: ViewGroup?): View { val itemView = view ?: LayoutInflater.from(ctx).inflate(_layoutId, parent, false) // 通过工厂函数创建ViewHolder实例 val viewHolder = viewHolderFactory(itemView) // 调用绑定数据的方法(假设NexusViewHolder有bind方法) viewHolder.bind(items[position]) return itemView } }
子类实现示例
当你继承NexusAdapter时,只需要传递对应的ViewHolder构造逻辑即可:
// 自定义的ViewHolder class UserViewHolder(itemView: View) : NexusViewHolder<UserData>(itemView) { override fun bind(data: UserData) { // 这里写绑定数据到View的逻辑,比如: itemView.tv_username.text = data.username } } // 自定义Adapter class UserAdapter(ctx: Context, items: List<UserData>) : NexusAdapter<UserData, UserViewHolder>( ctx, R.layout.item_user, items, // 传递工厂函数,直接创建UserViewHolder { UserViewHolder(it) } )
方案2:使用反射(不推荐)
如果因为某些原因必须用反射,你需要传入ViewHolder的Class对象,然后通过反射调用构造函数创建实例。但这种方式存在性能损耗,且需要处理各种反射异常,类型安全性也较差。
修改抽象类代码
open abstract class NexusAdapter<TData: NexusIdProvider, TViewHolder: NexusViewHolder<TData>> ( protected val ctx: Context, private val _layoutId: Int, protected val items: List<TData>, // 传入ViewHolder的Class对象,用于反射创建实例 private val viewHolderClass: Class<TViewHolder> ): BaseAdapter() { override fun getView(position: Int, view: View?, parent: ViewGroup?): View { val itemView = view ?: LayoutInflater.from(ctx).inflate(_layoutId, parent, false) try { // 获取接收View参数的构造函数 val constructor = viewHolderClass.getConstructor(View::class.java) // 创建ViewHolder实例 val viewHolder = constructor.newInstance(itemView) // 绑定数据 viewHolder.bind(items[position]) } catch (e: Exception) { // 处理反射可能出现的异常:比如没有对应构造函数、权限问题等 throw RuntimeException("Failed to initialize ViewHolder instance", e) } return itemView } }
子类实现示例
class UserAdapter(ctx: Context, items: List<UserData>) : NexusAdapter<UserData, UserViewHolder>( ctx, R.layout.item_user, items, // 传入UserViewHolder的Class对象 UserViewHolder::class.java )
为什么不能直接创建?
核心原因是泛型类型擦除:在编译完成后,TViewHolder这个泛型类型会被替换成它的上界(这里是NexusViewHolder<TData>),运行时JVM并不知道具体的子类类型,所以没法直接实例化。必须通过子类传递具体的创建逻辑或者Class信息来绕过这个限制。
内容的提问来源于stack exchange,提问作者Simple Fellow
相关产品推荐
相关产品推荐

