0

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

  • Recyclerview should internally determine current item view type and recycle/create correct viewholder for given position. Please expand your question with code sample of how you update your list, notify adapter of changes and how your adapter viewtype logic looks like (getitemviewtype and onbindviewholder - especially the part where you encounter the error). – Pawel Jun 24 '20 at 19:10
  • I added parts of the code. Someone said, I need to override getItemViewTyp()) but I do not know exactly how this helps, since the information, which viewtype and which older is used are provided with the item. I'm not sure in which order these functions are called by the system. – regentropfen Jun 25 '20 at 08:23
  • Is this supposed to be your `RecyclerView.Adapter` code? Where is `onBindViewHolder` and `onCreateViewHolder`? Also what is `createSushiViewHolder` and why does it have `index`? ViewHolder creation is not supposed to be aware of position – Pawel Jun 25 '20 at 11:40
  • As I said, it is an extended version, that does some Data loading/paging and caching stuff in-between, but in the end its a recycler view. The corresponding recycler view functions are called by these functions. I have to mention, that I'm not the original creator of these classes. I got have to work with this now. The guy who created this has left the. company. – regentropfen Jun 26 '20 at 09:34

0 Answers0