I have an extended Recycler View and put different view in there. These view holders are not compatible with each other and on reload they can be needed in a mixed order. I saw a lot of similar solutions, for example this one:
How to create RecyclerView with multiple view type?
They say I should cast the correct view type. Well I did that, but as expected, since its different kind of news, which do not have the same type in the same order, the types mismatch, when I make a type cast in onBindViewHolder. So I need a solution, to make him find a matching viewholder, when recycling. the one that is next to be recycled might have the wrong type. Is that possible somehow?
or another solution would be to clear the existing viewholders, when new data is loaded. I tried both, but didn't find a working solution.
Here is some code:
override fun createSushiViewHolder(parent: ViewGroup): SushiViewHolder {
val index = parent.childCount
val item = items[index]
var view: FrameLayout
when (item.widget_type) {
"webview" -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_stream_webview, parent, false) as FrameLayout
return WebViewHolder(view);
}
"player_details" -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_sushi_player_details, parent, false) as FrameLayout
return PlayerViewHolder(view);
}
"lifestyle_news" → {
and so on ....
override fun bindShushiViewHolder(holder: SushiViewHolder, position: Int) {
// if (holder !is NewsViewHolder) return
// Log.v("Widget", "ItemNumber: ${itemCounter} ")
val item = items[position]
when (item.widget_type) {
"webview" -> {
with(holder as WebViewHolder) {
with(items[position]) {
textTv.text = text
mainView.setOnClickListener {
if (urlAndroid != null) {
Navigation.findNavController(fragmentsContainer).navigate(
MainDirections.ActionGlobalWebview(Uri.parse(urlAndroid)))
}
}
}
}
}
"player_details" -> {
with(holder as PlayerViewHolder) {
with(items[position]) {
playerTv.text = "$firstname $lastname"
quoteTv.text = quote
if (quote != null) {
// shareBtn.makeShareButton(quote, shareLink, SharePresenter.Type.PLAYER)
}
GlideApp.with(holder.itemView)
.load(signImageUrl(images.playerQuote?.url.orEmpty(), width = viewWidth, imageType = ImageType.PLAYER))
.into(imageIv)
openProfilBtn.setOnClickListener {
if (id != null) {
// navigateToPlayerDetail(players?.firstOrNull()?.id.orEmpty())
navigateToPlayerDetail(id)
}
}
followBtn.setOnClickListener {
if (id != null) {
// navigateToPlayerDetail(players?.firstOrNull()?.id.orEmpty())
navigateToPlayerDetail(id)
}
}
openProfilTv.text = resources.getString(R.string.view_profile)
}
}
}"news" -> {
with(holder as NewsViewHolder) {
with(items[position]) {
headlineTv.text = headline
boxTitleTv.text = boxTitleTv.text.toString().capitalize()
timeTv.text = timeago
poweredByTv.text = """Powered by: $contentProvider"""
// authorTv.text = itemView.context.getString(R.string.powered_by, author)
GlideApp.with(holder.itemView)
.load(signImageUrl(images?.firstOrNull()?.url.orEmpty(), width = viewWidth, imageType = ImageType.NEWS_IMAGE))
.into(imageIv)
itemView.setOnClickListener {
if (id != null) {
navigateToNewsDetail(id)
}
}
readNewsCl.setOnClickListener {
if (id != null) {
navigateToNewsDetail(id)
}
}
headline?.let { shareBtn.makeShareButton(it, shareLink, SharePresenter.Type.NEWS) }
readArticleTv.text = resources.getString(R.string.read_article)
}
}
}
There are some more views.
The error I get mostly, is that NewsViewHolder can not be cast to WebViewHolder
Any suggestions? Thanks