I have a list of a class called Opportunity, which is filled with objects that extend Opportunity. The list can have either CommunityOpportunites or SponsorshipOpportunities.
I override getItemViewType and assign a value to each item based on whichever subclass the object in the relevant postition, and have a different ViewHolder for each:
override fun getItemViewType(position: Int): Int {
return if (opportunityList[position] is SponsorshipOpportunity){
Log.i(TAG,"Item type is sponsorshipId")
SPONSORSHIP
} else{
Log.i(TAG,"Item type is community")
COMMUNITY
}
}
inner class CommunityViewHolder(var view: CommunityTileBinding):RecyclerView.ViewHolder(view.root)
inner class SponsorshipViewHolder(var view: SponsorshipTileBinding):RecyclerView.ViewHolder(view.root)
companion object{
private const val COMMUNITY = 0
private const val SPONSORSHIP = 1
}
In onCreateViewHolder() I create the proper ViewHolder for the class of the item, and in onBindViewHolder() I attempt to cast the items in the list (of type Opportunity in the constructor) to the subclass of the item in the view:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType){
COMMUNITY->CommunityViewHolder(DataBindingUtil.inflate(inflater, R.layout.community_tile, parent, false))
SPONSORSHIP-> SponsorshipViewHolder(DataBindingUtil.inflate(inflater, R.layout.sponsorship_tile, parent, false))
else-> throw IllegalArgumentException()
}
}
override fun getItemCount(): Int = opportunityList.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder.itemViewType){
COMMUNITY-> {
(holder as CommunityViewHolder).view.communityOpportunity = opportunityList[position] as CommunityOpportunity
}
SPONSORSHIP->{
(holder as SponsorshipViewHolder).view.sponsorship = opportunityList[position] as SponsorshipOpportunity
holder.view.postActionText.text = context.resources.getString(R.string.watch_respond)
}
}
}
However, I get the following class cast exception
java.lang.ClassCastException: com.example.model.Opportunity cannot be cast to com.example.model.CommunityOpportunity
when I try at the relevant line in onBindViewHolder, even though the log statement confirming that the item is a CommunityOpportunity in getItemViewType() is printed.
Is there a better way to ask, or is there a better way for me to be displaying multiple ViewHolder/Object types in the RecyclerView?
Edit: Here are the relevant xml layouts:
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="sponsorship"
type="com.example.weare8sample.model.SponsorshipOpportunity"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:elevation="2dp"
android:orientation="vertical"
android:background="@drawable/tile_background">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="@drawable/tile_background"
android:imageUrl="@{sponsorship.coverTileUri}">
</ImageView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:padding="10dp">
<TextView
android:id="@+id/postActionText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lato_bold"
tools:text="@string/watch_respond">
</TextView>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/ic_chevron_right_black_36dp">
</ImageView>
</RelativeLayout>
</LinearLayout>
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="communityOpportunity"
type="com.example.weare8sample.model.CommunityOpportunity" />
</data>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/tile_background"
android:imageUrl="@{communityOpportunity.mediaImageUri}">
</ImageView>
Add an explicit type check for all types in getItemViewType
and throw if it's an unknown type, to properly handle all cases.
As it is now, if there's a 3rd type of Opportunity, it will be assumed to be of COMMUNITY
type.