如何在Kotlin中创建具体化(reified)类型的RecyclerView.ViewHolder对象?
Great question! You’re already on the right track using reified generics—this lets us access the actual type of T at compile time, which is key to solving this problem. Here’s how to properly create and return an instance of your ViewHolder subclass:
Solution 1: Compile-Time Safe Constructor Call (Recommended)
Most custom RecyclerView.ViewHolder implementations follow the standard pattern of having a primary constructor that takes a View (since RecyclerView.ViewHolder itself requires this). With reified generics, you can directly call this constructor:
inline fun <reified T : RecyclerView.ViewHolder> ViewGroup.createViewHolder(@LayoutRes res: Int): T { val inflater = LayoutInflater.from(context) val itemView = inflater.inflate(res, this, false) // Directly invoke the ViewHolder's constructor with the inflated view return T(itemView) }
Key Details:
- This approach is type-safe: The compiler will throw an error if your
Tsubclass doesn’t have a primary constructor accepting a singleViewparameter. - There’s no runtime reflection overhead, so it’s performant for RecyclerView’s fast scrolling needs.
Solution 2: Reflection-Based Approach (For Edge Cases)
If you need to support ViewHolders with non-primary constructors (a rare scenario), you can use reflection to instantiate the class. Note that this adds runtime overhead and requires exception handling:
inline fun <reified T : RecyclerView.ViewHolder> ViewGroup.createViewHolder(@LayoutRes res: Int): T { val inflater = LayoutInflater.from(context) val itemView = inflater.inflate(res, this, false) return try { // Look up and invoke the constructor that takes a View parameter T::class.java.getConstructor(View::class.java).newInstance(itemView) } catch (e: NoSuchMethodException) { throw IllegalArgumentException("Your ViewHolder must have a constructor that accepts a single View parameter", e) } catch (e: IllegalAccessException) { throw RuntimeException("Could not access the ViewHolder constructor", e) } catch (e: InstantiationException) { throw RuntimeException("Could not instantiate the ViewHolder", e) } }
Example Usage
Suppose you have a standard ViewHolder like this:
class MyItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { // Add your view bindings or logic here }
You can use the extension function in your adapter’s onCreateViewHolder method:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyItemViewHolder { return parent.createViewHolder<MyItemViewHolder>(R.layout.item_my) }
内容的提问来源于stack exchange,提问作者Samuel Robert

