Created
August 5, 2021 06:57
-
-
Save sergei-lapin/66d37fb628350334a5c378c9aebdb1df to your computer and use it in GitHub Desktop.
Full Supplier code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typealias ViewHolderProducer = (parent: ViewGroup, viewType: Int) -> RecyclerView.ViewHolder | |
typealias ViewHolderConsumer = (viewHolder: RecyclerView.ViewHolder, creationTimeNanos: Long) -> Unit | |
abstract class ViewHolderSupplier( | |
context: Context, | |
private val viewHolderProducer: ViewHolderProducer | |
) { | |
internal lateinit var viewHolderConsumer: ViewHolderConsumer | |
private val fakeParent: ViewGroup by lazy { FrameLayout(context) } | |
private val mainHandler: Handler = Handler(Looper.getMainLooper()) | |
private val itemsCreated: MutableMap<Int, Int> = ConcurrentHashMap<Int, Int>() | |
private val itemsQueued: MutableMap<Int, Int> = ConcurrentHashMap<Int, Int>() | |
private val nanoTime: Long get() = System.nanoTime() | |
abstract fun start() | |
abstract fun enqueueItemCreation(viewType: Int) | |
abstract fun stop() | |
protected fun createItem(viewType: Int) { | |
val created = itemsCreated.getOrZero(viewType) + 1 | |
val queued = itemsQueued.getOrZero(viewType) | |
if (created > queued) return | |
val holder: RecyclerView.ViewHolder | |
val start: Long | |
val end: Long | |
try { | |
start = nanoTime | |
holder = viewHolderProducer.invoke(fakeParent, viewType) | |
end = nanoTime | |
} catch (e: Exception) { | |
return | |
} | |
holder.setItemViewType(viewType) | |
itemsCreated[viewType] = itemsCreated.getOrZero(viewType) + 1 | |
mainHandler.postAtFrontOfQueue { viewHolderConsumer.invoke(holder, end - start) } | |
} | |
internal fun setPrefetchBound(viewType: Int, count: Int) { | |
if (itemsQueued.getOrZero(viewType) >= count) return | |
itemsQueued[viewType] = count | |
val created = itemsCreated.getOrZero(viewType) | |
if (created >= count) return | |
repeat(count - created) { enqueueItemCreation(viewType) } | |
} | |
internal fun onItemCreatedOutside(viewType: Int) { | |
itemsCreated[viewType] = itemsCreated.getOrZero(viewType) + 1 | |
} | |
private fun Map<Int, Int>.getOrZero(key: Int) = getOrElse(key) { 0 } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment