I know the title is a bit weird, sorry. This is a weird one that I'm not even sure I can explain it correctly, here is my attempt:
Basically I want to implement a wrapper for any adapters that extend RecyclerView.Adapter<RecyclerView.ViewHolder> , the wrapper eventually will be able to insert rows if needed and it will modify things like getItemCount() as necessary, but I'm nowhere near that part yet.
This is my class definition:
class MyRecyclerAdapterWrapper(activity: Activity,val originalAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
I pass to it the original adapter which I want to wrap.
If I have the class definition like that, and then I try to create an instance of MyRecyclerAdapterWrapper like this:
val wrapper = MyRecyclerAdapterWrapper(activity, myOriginalAdapter)
Where myOriginalAdapter is an instance of:
class MyOriginalAdapter() : RecyclerView.Adapter<MyOriginalAdapter.MyViewHolder>() {
I then get an error saying that it is expecting RecyclerView.Adapter<RecyclerView.ViewHolder> but instead got MyOriginalAdapter.
So then I tried the out keyword on the class definition like this:
class MyRecyclerAdapterWrapper(activity: Activity,val originalAdapter: RecyclerView.Adapter<out RecyclerView.ViewHolder>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
And that allows my constructor call MyRecyclerAdapterWrapper(activity, myOriginalAdapter) to stop complaining, however then my MyRecyclerAdapterWrapper class fails at implementing some of the RecyclerView.Adapter<RecyclerView.ViewHolder> overrides because originalAdapter expects Nothing instead of RecyclerView.ViewHolder.
For example inside MyRecyclerAdapterWrapper I have this piece of code:
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
originalAdapter.onBindViewHolder(holder,position)
}
The error here is Type mismatch Required: Nothing Found: RecyclerView.ViewHolder.
So what is the correct way to handle this?
Edit: just wanted to be clear that other adapters will also use this wrapper, so the wrapper must be generic.
Edit: I should have mentioned this, there is a similar wrapper that works fine that I was using but it is in Java, the class definition on that one was:
public final class MyRecyclerAdapterWrapper extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
public MyRecyclerAdapterWrapper(@NonNull Activity activity,
@NonNull RecyclerView.Adapter originalAdapter){
Edit: Based on the answer from @muetzenflo I was able to get most of it to work but still have a problem with some methods.
I now have this:
class MyRecyclerAdapterWrapper<T : RecyclerView.ViewHolder>(activity: Activity, val originalAdapter: RecyclerView.Adapter<T>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
And
class MyCustomAdapter(): RecyclerView.Adapter<MyCustomAdapter.MyViewHolder>(){
class MyViewHolder(v: View): RecyclerView.ViewHolder(v) {
}
This works:
val myRecyclerAdapterWrapper = MyRecyclerAdapterWrapper(this, MyCustomAdapter())
But this doesn't:
genericMethod(myRecyclerAdapterWrapper)
private fun genericMethod(myRecyclerAdapterWrapper: MyRecyclerAdapterWrapper<RecyclerView.ViewHolder>) {
}
The error is:
Type mismatch: inferred type is MainActivity.MyRecyclerAdapterWrapper<MainActivity.MyCustomAdapter.MyViewHolder> but MainActivity.MyRecyclerAdapterWrapper<RecyclerView.ViewHolder> was expected
Edit: Think I figured out how to make the generic methods:
private fun <T> genericMethod(myRecyclerAdapterWrapper: MyRecyclerAdapterWrapper<T> ) where T : RecyclerView.ViewHolder {
}
So in the end this is how my class ended up and it all compiles and runs:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myRecyclerAdapterWrapper = MyRecyclerAdapterWrapper(this, MyCustomAdapter())
genericMethod(myRecyclerAdapterWrapper)
}
private fun <T> genericMethod(myRecyclerAdapterWrapper: MyRecyclerAdapterWrapper<T> ) where T : RecyclerView.ViewHolder {
}
class MyRecyclerAdapterWrapper<T : RecyclerView.ViewHolder>(activity: Activity, val originalAdapter: RecyclerView.Adapter<T>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return originalAdapter.onCreateViewHolder(parent,viewType)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
originalAdapter.onBindViewHolder(holder as T,position)
}
override fun getItemCount(): Int {
return originalAdapter.itemCount
}
}
class MyCustomAdapter(): RecyclerView.Adapter<MyCustomAdapter.MyViewHolder>(){
class MyViewHolder(v: View): RecyclerView.ViewHolder(v) {
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
TODO("Not yet implemented")
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
TODO("Not yet implemented")
}
}
}