RecyclerView changing image incorrectly onNotifyItemChanged - android

I'm having this issue, with recyclerView, may you check two screenshots below:
So that's my issue, when onNotifyItemChange runs, other info are changed, incorrectlty. Now here goes my adapter:
class TimelineAdapter(var timeline: TimelineDTO,
var toggleLikeClicked: OnRowClick,
var onCommentClicked: OnRowClick,
var onMediaClick: OnRowClick,
val onUserClicked: OnRowClick,
val reportPost: OnRowClick,
val editPost : OnRowClick,
val deletePost: OnRowClick,
val contract: TimelineViewContract) : BaseAdapter<RecyclerView.ViewHolder>() {
init {
setHasStableIds(true)
}
private var currentItem: Int = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (PostType.fromInt(viewType)) {
PostType.BASIC -> {
return PostViewHolder(parent.inflate(R.layout.row_post_default_item),
toggleLikeClicked, onCommentClicked, onMediaClick,
onUserClicked, reportPost,
editPost,
deletePost,
FirebaseAnalytics.getInstance(contract.returnContext()))
}
PostType.NEXT_TALKS -> {
return PostNextTalksViewHolder(parent.inflate(R.layout.row_post_next_talks_item),
contract)
}
else -> {
if(!BuildConfig.DEBUG) {
Crashlytics.log("Should not come here")
}
logE("adapter else!!")
return PostViewHolder(parent.inflate(R.layout.row_post_default_item),
toggleLikeClicked, onCommentClicked, onMediaClick,
onUserClicked, reportPost,
editPost,
deletePost,
FirebaseAnalytics.getInstance(contract.returnContext()))
}
}
}
override fun getItemCount(): Int {
var count = timeline.posts.size
if(hasValue(timeline.nextTalks.size)){
count++
}
return count
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
currentItem = position
val alignedPositon = getAlignedPosition(position)
when (holder) {
is PostViewHolder -> holder.bind(timeline.posts[alignedPositon])
is PostNextTalksViewHolder -> {
holder.bind(timeline.nextTalks)
}
is PostCarousselViewHolder -> {
holder.bind(ArrayList<String>())
}
}
}
fun getPostAt(position: Int): PostDTO {
val post: PostDTO
val alignedPositon = getAlignedPosition(position)
post = timeline.posts[alignedPositon]
return post
}
override fun getItemId(position: Int): Long {
val aligned = getAlignedPosition(position)
return aligned.toLong()
}
private fun getAlignedPosition(position: Int): Int {
var alignedPositon = position
if (hasValue(timeline.nextTalks.size)){
alignedPositon--
}
return alignedPositon
}
override fun getItemViewType(position: Int): Int {
val hasPinned = timeline.posts.any { it.postType == PostType.PINNED.id }
if(hasPinned) {
if(position == 1 && timeline.nextTalks.any()){
return PostType.NEXT_TALKS.id
}
}
else {
if(position == 0 && timeline.nextTalks.any()){
return PostType.NEXT_TALKS.id
}
}
return timeline.posts[getAlignedPosition(position)].postType
}
fun updateItemAt(postLocal: PostLocal, commentIndexPost: Int) {
timeline.posts.removeAt(commentIndexPost)
timeline.posts.add(commentIndexPost, PostDTO(postLocal))
notifyItemChanged(commentIndexPost)
}
fun addItems(newPosts: TimelineDTO) {
timeline.posts.addAll(newPosts.posts)
timeline.nextTalks.addAll(newPosts.nextTalks)
notifyItemRangeInserted(itemCount, newPosts.posts.size)
}
fun resetItems(nextPosts: TimelineDTO) {
timeline.posts.clear()
timeline.nextTalks.clear()
timeline.posts.addAll(nextPosts.posts)
timeline.nextTalks.addAll(nextPosts.nextTalks)
notifyDataSetChanged()
}
fun removeAt(position: Int) {
timeline.posts.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, timeline.posts.size)
}
}

Using notifyItemChanged() might trigger "fading in and out" effect which is not necessarily desired (unless You use stable IDs or killed change animation in animator).
If You know what was changed in an item, it's better to use an update payload (see an example here) to partially update your ViewHolders without triggering full rebind.
Otherwise if list is relatively small and You don't know what changed, you can also use DiffUtil to help generate list of changes/change payloads "semi-automatically".

Related

How to deselect items in recycler view and validate it?

I am beginner in Android Kotlin , I am developing app which requires a selected data from recycler view to be in an arraylist. selection work fine ,if i selected item it will validate the value is null or not. if value not null button will enable. the problem is when i unselected item, the button is still enable and item still not removed from the selected data arrayList(data from API). if someone could help me to solve the issue, will be very glad. Thanks a lot. here is my code
private var checkPosition = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GridViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_pul, parent, false)
return GridViewHolder(view)
}
override fun onBindViewHolder(holder: GridViewHolder, position: Int) {
holder.bindPul(listPul[position], listener)
}
override fun getItemCount(): Int {
return listpul.size
}
inner class GridViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
fun bindPul(pul: Model, listener: OnItemClickListener) = with(itemView){
val binding = ItemPBinding.bind(itemView)
binding.lblPayAmount.text = p.ModelValue.toDouble().currencyFormatter()
when (checkPosition) {-1 -> {
binding.itemPul.setCardBackgroundColor(Color.WHITE)
binding.itemPul.strokeColor = Color.parseColor("#DDEBF9")
binding.lblCheck.setVisible(false)
}else -> when(checkPosition){
absoluteAdapterPosition -> {
binding.itemPul.setCardBackgroundColor(Color.parseColor("#F5FAFF"))
binding.itemPul.strokeColor = Color.TRANSPARENT
binding.lblCheck.setVisible(true)
}else -> {
binding.itemP.setCardBackgroundColor(Color.WHITE)
binding.itemP.strokeColor = Color.parseColor("#DDEBF9")
binding.lblCheck.setVisible(false)
}
}
}
setOnClickListener {
binding.itemPul.setCardBackgroundColor(Color.parseColor("#F5FAFF"))
binding.itemPul.strokeColor = Color.TRANSPARENT
binding.lblCheck.setVisible(true)
if (checkPosition != absoluteAdapterPosition){
notifyItemChanged(checkPosition)
checkPosition = absoluteAdapterPosition
}
else{
binding.itemPul.setCardBackgroundColor(Color.WHITE)
binding.itemPul.strokeColor = Color.parseColor("#DDEBF9")
binding.lblCheck.setVisible(false)
}
listener.onItemClick(pul)
}
}
}
fun updateChecked(item: Model){
listp.mapIndexed { _, Model -> Model.isSelected = Model.ModelValue == item.ModelValue}
notifyItemChanged(checkPosition)
notifyDataSetChanged()
}
interface OnItemClickListener {
fun onItemClick(pul: Model)
}
}

Number of item submit in PagingDataAdapter

How to get number of items submitted to PagingDataAdapter
I have to display a RecyclerView with multiple viewType as Start, Middle and End RecyclerView.ViewHolder
Start and End ViewHolder is round where as inner items are using MiddleViewHolder
After debug I evaluate that when i submit 2 items to PagingDataAdapter
itemCount is still 1.
How to check total item submit in PagingDataAdapter
StartViewHolder -> bindData(item,itemCount == 1)
RecentPagerAdapter.kt
const val VIEW_TYPE_FIRST = 0
const val VIEW_TYPE_MIDDLE = 1
private const val VIEW_TYPE_LAST = 2
class RecentPagerAdapter(val clicked:(recent:RecentBO) -> Unit) : PagingDataAdapter<RecentBO, RecyclerView.ViewHolder>(recentDiffUtil) {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
getItem(position)?.let { item ->
when (getItemViewType(position)) {
VIEW_TYPE_FIRST -> (holder as StartViewHolder).bindData(item,itemCount == 1)
VIEW_TYPE_MIDDLE -> (holder as RecentViewHolder).bindData(item)
VIEW_TYPE_LAST -> (holder as EndViewHolder).bindData(item)
}
}
}
override fun getItemViewType(position: Int): Int {
return when (position) {
0 -> VIEW_TYPE_FIRST
1 -> VIEW_TYPE_MIDDLE
else -> VIEW_TYPE_LAST
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType) {
VIEW_TYPE_FIRST -> StartViewHolder(ItemCurveStartBinding.inflate(LayoutInflater.from(parent.context),parent,false)){
getItem(it)?.let { clicked.invoke(it) }
}
VIEW_TYPE_LAST -> EndViewHolder(ItemCurveEndBinding.inflate(LayoutInflater.from(parent.context),parent,false)){
getItem(it)?.let { clicked.invoke(it) }
}
else -> RecentViewHolder(ItemRecentBinding.inflate(LayoutInflater.from(parent.context),parent,false)){
getItem(it)?.let { clicked.invoke(it) }
}
}
}
companion object {
private val recentDiffUtil = object : DiffUtil.ItemCallback<RecentBO>() {
override fun areItemsTheSame(oldItem: RecentBO, newItem: RecentBO): Boolean {
return oldItem.localPath == newItem.localPath && oldItem.imageUrl == newItem.imageUrl
}
override fun areContentsTheSame(oldItem: RecentBO, newItem: RecentBO): Boolean {
return oldItem == newItem
}
}
}
}
If there is only one item in list then all sides should be rounded.otherwise above image and last item should be rounded also.
StartViewHolder.kt
class StartViewHolder(val itemBinding: ItemCurveStartBinding,
val clicked:(pos:Int) -> Unit): RecyclerView.ViewHolder(itemBinding.root) ,
View.OnClickListener{
init {
itemView.setOnClickListener(this)
}
fun bindData(recentBO: RecentBO,onlyOneItem:Boolean){
itemBinding.item = recentBO
val radius: Float = 30.0f//getResources().getDimension(R.dimen.default_corner_radius)
if(onlyOneItem){
itemBinding.ivPhoto.shapeAppearanceModel = itemBinding.ivPhoto.shapeAppearanceModel
.toBuilder()
.setTopLeftCorner(CornerFamily.ROUNDED,radius)
.setBottomLeftCorner(CornerFamily.ROUNDED,radius)
.setTopRightCorner(CornerFamily.ROUNDED,radius)
.setBottomRightCorner(CornerFamily.ROUNDED,radius)
.build();
}else {
itemBinding.ivPhoto.shapeAppearanceModel = itemBinding.ivPhoto.shapeAppearanceModel
.toBuilder()
.setTopLeftCorner(CornerFamily.ROUNDED,radius)
.setBottomLeftCorner(CornerFamily.ROUNDED,radius)
.build();
}
}
override fun onClick(p0: View?) {
clicked.invoke(absoluteAdapterPosition)
}
}
I think something mistake in below code
(holder as StartViewHolder).bindData(item,itemCount == 1)
there are 2 items in RecyclerView but itemCount shows 1
What am i missing or doing wrong??
When I added an item to it First item remain fully rounded.
Code for initializing adapter
private val recentPagerAdapter by lazy { RecentPagerAdapter{
openPreview(PhotoBO(it.localPath))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mViewModel.getRecentPhotos().observe(viewLifecycleOwner)
{
recentPagerAdapter
.submitData(viewLifecycleOwner.lifecycle,it)
recentPagerAdapter.notifyDataSetChanged()
}
}
Please See Edit
itemCount and snapshot().items.size is 1 where as I have submitData 2 items to PagingDataAdapter
How to know total item submitted to PagingDataAdapter inside onBindViewHolder ?

Recyclerview selection: createSelectSingleAnything selects multiple when scrolling

I'm trying to create a horizontal recyclerview with a single selection. The code below works but if you scroll, then 2 or more objects can be selected, even though I specify the single selection. I guess it's because the onBindViewHolder is not called if the item is off the screen but when I call the notifyDataSetChanged the behavior is still the same. The callbacks are correct, but the selector background, shows behind multiple objects.
class CategoryAdapter(private val listener: CategoryListener) :
ListAdapter<CategoryListing, CategoryAdapter.ViewHolder>(CategoryListing.DIFF_COMPARATOR) {
init {
setHasStableIds(true)
}
var tracker: SelectionTracker<Long>? = null
...
override fun getItemId(position: Int): Long = position.toLong()
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
tracker?.let {
if (!it.hasSelection() && position == 0) {
it.select(0)
}
}
holder.bind(
currentList[position],
listener,
tracker?.isSelected(position.toLong()) ?: false
)
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(
category: CategoryListing,
listener: CategoryListener,
isSelected: Boolean
) {
if (isSelected) selector.show() else selector.hide()
itemView.setOnClickListener {
tracker?.clearSelection() // this doesn't seem to do anything
// notifyDataSetChanged() // neither this
// tracker?.select(adapterPosition.toLong()) // or this
listener.onItemClicked(category, adapterPosition)
}
}
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition() = adapterPosition
override fun getSelectionKey() = itemId
}
}
Fragment:
rv_categories.adapter = categoryAdapter
rv_categories.setHasFixedSize(true)
selectionTracker = SelectionTracker.Builder<Long>(
CardsFragment::javaClass.name,
rv_categories,
CategoryItemKeyProvider(rv_categories),
CategoryDetailsLookup(rv_categories),
StorageStrategy.createLongStorage()
).withSelectionPredicate(SelectionPredicates.createSelectSingleAnything()).build()
categoryAdapter.tracker = selectionTracker
selectionObserver = CategorySelectionObserver(selectionTracker) { selectedPosition ->
onSelectionChanged(selectedPosition)
}
selectionTracker.addObserver(selectionObserver)
...
override fun onItemClicked(category: CardCategoryListing, position: Int) {
// load the data for that category
}
private fun onSelectionChanged(selectedItemPosition: Long) {
rv_categories.findViewHolderForAdapterPosition(selectedItemPosition.toInt())?.itemView?.performClick()
}
Can anyone help?

Why onLongclicklistener does no work in onBindviewholder with kotlin

I have looked for solutions to this problem but cannot find an answer.
I can get my onClickListener to work (Kotlin) from inside the onBindViewHolder of my Adapter but the onLongClickListener (Kotlin) does not respond, even though the code is not showing an error
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val ingredientdisplay=displayItems[position]
holder.setData(ingredientdisplay,position)
runningTotal=runningTotal+holder.itemView.tvcost.text.toString().toDouble()
println ("running total $runningTotal")
val intent = Intent("message_from_displayadapter")
intent.putExtra("runningtotal", runningTotal)
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
holder.itemView.setOnLongClickListener {view->
println("longclick")
true
}
holder.itemView.setOnClickListener {
val intent = Intent(context, ChooseIngredientsActivity::class.java)
ContextCompat.startActivity(context, intent, null)
}
}
I am just trying to println or run a Toast but nothing happens.
I don't understand why? Your help would be appreciated.
First don't put your onClicklistiner in onBindViewHolder it's not good practice, use update your Adapter Class like this one also OnLongclicklistiner is working fine
class NewsAdapter (val context: Context, private val arrayList: ArrayList
<NewsModel>):
RecyclerView.Adapter <NewsAdapter.Holder> () {
companion object {
// val TAG: String = OperationAdapter::class.java.simpleName
}
override fun onCreateViewHolder (parent: ViewGroup, viewType: Int): Holder {
return Holder (LayoutInflater.from (parent.context ).inflate (R.layout.newsitemlist , parent, false))
}
override fun getItemCount (): Int = arrayList. size
override fun onBindViewHolder (holder: Holder, position: Int) {
val mynews= arrayList[position]
holder.setData(mynews, position)
}
inner class Holder (itemView: View): RecyclerView.ViewHolder (itemView) {
private var currentnews: NewsModel? = null
private var currentPosition: Int = 0
init {
//The click listener
itemView.cardview.setOnClickListener {
val i = Intent(context,NewsReaderActivity::class.java)
i.putExtra("body",currentnews!!.body)
i.putExtra("title",currentnews!!.title)
context.startActivity(i)
}
itemView.cardview.setOnLongClickListener{
Toast.makeText(context,"Long Clicked",Toast.LENGTH_SHORT).show()
true
}
//the end of the init
}
//getting data from model and bind it into View
fun setData(news: NewsModel?, position: Int) {
news?.let {
itemView.newstitle.text = news.title
itemView.body.text = news.body
itemView.txtdate.text = news.ndate
}
this.currentnews = news
this.currentPosition = position
}
}
}
I have moved the listeners to the inner class the code for the complete adaper is below. Still the onLongClicListener is not responding.
class RecipiesDisplayAdapter(val context:Context, val displayItems:List):RecyclerView.Adapter(){
var runningTotal:Double=0.00
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view= LayoutInflater.from(context).inflate(R.layout.recipedisplay_list,parent,false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return displayItems.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val ingredientdisplay=displayItems[position]
holder.setData(ingredientdisplay,position)
runningTotal=runningTotal+holder.itemView.tvcost.text.toString().toDouble()
println ("running total $runningTotal")
val intent = Intent("message_from_displayadapter")
intent.putExtra("runningtotal", runningTotal)
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
}
inner class MyViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
private var currentIngredientDisplay:IngredientDisplay?=null
private var currentPosition:Int=0
init {
itemView.setOnLongClickListener {
Log.i ("clicked ", "longclick")
context.showToast("longClicked")
true
}
itemView.setOnClickListener {
val intent = Intent(context, ChooseIngredientsActivity::class.java)
ContextCompat.startActivity(context, intent, null)
}
}
fun setData(ingredientdisplay: IngredientDisplay?, pos:Int){
val fromrate=getfromdb(ingredientdisplay!!.unitPurchased)
val torate =getfromdb(ingredientdisplay!!.unitPerRecipe)
val minunitcost= ingredientdisplay!!.costPurchased/ingredientdisplay!!.quantityPurchased/fromrate
val costperrecipe=minunitcost*ingredientdisplay!!.quantityPerRecipe*torate
val s = String.format( "%.2f", costperrecipe);
val pdu=ingredientdisplay!!.quantityPerRecipe.toString()+" "+ingredientdisplay!!.unitPerRecipe
ingredientdisplay?.let {
itemView.tvIngredientName.text = ingredientdisplay!!.ingredientName
itemView.tvcost.text = s
itemView.tvqty.text = pdu
}
this.currentPosition=pos
this.currentIngredientDisplay=ingredientdisplay
}
fun getfromdb (unit:String) :Double{
var sendback:String=""
context.database.use {
select("Units", "convertionrate")
.`whereSimple`("unitname = ?", unit)
.exec {
parseList(DoubleParser).forEach{
println("result $it")
val resu= it.toString()
sendback=resu
}
}
}
return sendback.toDouble()
}
}
}
I cannot figure out why!
The problem is solved. I made a rookie mistake. I added all the onclicklisteners to my adapters. Then later started to add onlongclicklisteners to them. Belive it or not. I was setting it in the wrong adapter. Appologies for your trouble however your answers where helpful.
context does not work sometimes or in the newer version
so you can use also
Toast.makeText(it.context, "Long Clicked", Toast.LENGTH_SHORT).show()

Recyclerview becoming heavy - Skipped frames

I have infinite scrolling RecyclerView with loading more items from API when scrolled to the last item, but after several scrolls my RecyclerView starting to lag on adding new items and getting
Skipped 197 frames! The application may be doing too much work on its main thread.
in the logs. I cannot find what is causing the lag.
Followings are my methods
val onLoadMore = object : IOnLoadMore {
override fun onLoadMore() {
if (!adapter.loadingMore) {
adapter.addLoadingItem()
requestSimple()
}
}
}
fun requestSimple() {
disposable = MyApplication.apiService.offerSearchWithPromo(
defaultSharedPreferences.getString(Config.PREF_LANG, Config.RU), request!!)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
adapter.removeLoadingItem()
adapter.items.addAll(it.offers.data)
if (it.promotions.data.size > 0) adapter.items.add(it.promotions.data)
adapter.notifyItemRangeInserted(adapter.items.size - it.offers.data.size - 1, it.offers.data.size)
adapter.meta = it.offers.meta
tv_found.text = resources.getString(R.string.found) + " " + adapter.meta?.pagination?.total.toString()
if (it.offers.data.size == 15) adapter.setOnLoadMoreListener(onLoadMore)
else adapter.removeListener()
request!!.page++
}, {
showError(it.message.toString())
})
}
and this is my adapter
class AdrResRvDynamic(var context: Context, nestedScrollView: NestedScrollView? = null, var items: MutableList<Any?>) : RVAdrMutableNullable<Any?, RecyclerView.ViewHolder>(items) {
var isLoading: Boolean = false
var meta: ObjMeta? = null
private var mIOnLoadMore: IOnLoadMore? = null
private val VIEW_TYPE_AUTO_SIMPLE = 0
private val VIEW_TYPE_AUTO_VIP = 1
private val VIEW_TYPE_AUTO_SUGGESTED = 2
private var VIEW_TYPE_LOADING = 99
var loadingMore: Boolean = false
var curr = ""
init {
curr = context.defaultSharedPreferences.getString(Config.PREF_CURRENCY, Config.UZS)
setHasStableIds(true)
nestedScrollView?.setOnScrollChangeListener { v: NestedScrollView, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int ->
if (v.getChildAt(v.childCount - 1) != null) {
isLoading = if (scrollY >= v.getChildAt(v.childCount - 1).measuredHeight - v.measuredHeight && scrollY > oldScrollY) {
if (mIOnLoadMore != null) mIOnLoadMore!!.onLoadMore()
true
} else false
}
}
}
fun setOnLoadMoreListener(mIOnLoadMore: IOnLoadMore) {
this.mIOnLoadMore = mIOnLoadMore
}
fun removeListener() {
this.mIOnLoadMore = null
}
override fun getItemViewType(position: Int): Int {
return when {
items[position] == null -> VIEW_TYPE_LOADING
items[position]!!::class.simpleName == "ObjAuto" -> VIEW_TYPE_AUTO_SIMPLE
items[position]!!::class.simpleName == "ObjAutoVip" -> VIEW_TYPE_AUTO_VIP
items[position] is List<*> -> VIEW_TYPE_AUTO_SUGGESTED
else -> VIEW_TYPE_LOADING
}
}
#Suppress("UNCHECKED_CAST")
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val obj = items[position]
when (holder) {
is ItemViewAutoCard -> holder.bind(obj!! as ObjAuto)
is ItemViewAutoCardSUGGESTED -> holder.bind(obj!! as List<ObjAuto>)
is ItemViewAutoCardVIP -> holder.bind(obj!! as ObjAutoVip)
is ItemViewLoadingMore -> {
// holder.itemView.find<ProgressBar>(R.id.progressBar1).isIndeterminate = true
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
VIEW_TYPE_AUTO_SIMPLE -> ItemViewAutoCard(context, LayoutInflater.from(parent.context).inflate(R.layout.li_auto_card, parent, false))
VIEW_TYPE_AUTO_VIP -> ItemViewAutoCardVIP(context, LayoutInflater.from(parent.context).inflate(R.layout.li_auto_card_vip, parent, false))
VIEW_TYPE_AUTO_SUGGESTED -> ItemViewAutoCardSUGGESTED(context, LayoutInflater.from(parent.context).inflate(R.layout.li_auto_card_suggested, parent, false))
else -> ItemViewLoadingMore(LayoutInflater.from(parent.context).inflate(R.layout.progress_bar_load_more, parent, false))
}
}
override fun getItemCount(): Int {
return items.size
}
fun removeLoadingItem() {
loadingMore = false
if (items.size == 0) return
items.removeAt(items.size - 1)
notifyItemRemoved(items.size)
}
fun addLoadingItem() {
loadingMore = true
items.add(null)
notifyItemInserted(items.size - 1)
}
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
super.onViewRecycled(holder)
}
}
PS: I've commented out all the logic inside my ItemViews so there's nothing going on in onBind() method, i'm just showing empty layout, but still after several loads the recycler becoming laggy.
Answering my own question, The problem was placing RecyclerView inside NestedScrollView. I needed it because there was a view above RecyclerView which needed to be scrolled. I've removed it and put it as a first item in my RecyclerView. What was happening is that the items in RecyclerView was not being recycled as its height was just expanding.
Verdict: Never put RecyclerView inside NestedScrollView

Categories

Resources