1

I have a RecyclerView that contains views that can be quite complex and their inflation make the scrolling choppy if they are inflated just in time. My idea was that I could pre-inflate the views in a background thread. I've tried it and it works really nice on the emulator as well as on my Pixel 3. To be clear, they are only inflated and not added to the parent ahead of time.

I found this SO thread, where they say that there seems to be an issue with Samsung Galaxy phones, but the thread is almost 10 years old, so i am not sure if this is still an issue.

Google of course says not to do it. See here. Although the reasons they mention (mostly memory leaks) don't apply in my case. Or at least I don't see a possible Activity leak here.

This is simplified what I am doing:

class MyRecyclerAdapter(
    private var items: List<Item>
) : RecyclerView.Adapter<MyViewHolder>() {

    // Map to hold the pre-cached views
    private val viewCache = mutableMapOf<Int, Deferred<View?>>()

    companion object {
        // Only inflate one view at a time
        val serialCoroutineDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
    }

    init {
        items.forEachIndexed { index, it ->
            viewCache[index] = CoroutineScope(serialCoroutineDispatcher).async {
                createViewForItem(it) // View is created asynchronously here
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        runBlocking {
            MyViewHolder(
                // If no view in cache, inflate here
                viewCache.remove(viewType)?.await() ?: createViewForItem(items[viewType])
            )
        }

    ...

Has anyone tried something similar? Or can someone speak to why I should not do it (besides leaking the Activity which is not an issue here)?

FYI: I'm aware of AsyncLayoutInflater, but I cannot use it for other reasons.

SimonSays
  • 10,867
  • 7
  • 44
  • 59

0 Answers0