Number of item submit in PagingDataAdapter - android

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 ?

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)
}
}

position of recyclerview item changes after opening the fragment again

I am using android kotlin. i am working on online shopping app.
in the shopping cart section. all things works fine.adding an item to cart or delete the item or adding quantity and undoing the delete .
when i click on undo button the item is placed in its own position after undoing the deleted item. but when i close the fragment and open it again all item position changes and the item that i clicked first will be first item and so to the end
this is my recycler adapter:
class BasketRecyclerAdapter(val list: MutableList<Model.BasketItem>, val listener: ButtonListener) :
RecyclerView.Adapter<BasketRecyclerAdapter.ViewHolder>() {
lateinit var context: Context
lateinit var localStore: LocalStore // i saved user phone and pass in a shared prefs using this class
inner class ViewHolder(val binding: BasketItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BasketRecyclerAdapter.ViewHolder {
val binding: BasketItemLayoutBinding = DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.basket_item_layout,
parent,
false
)
localStore = LocalStore(parent.context)
context = parent.context
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: BasketRecyclerAdapter.ViewHolder, position: Int) {
val currentItem = list[position]
holder.binding.apply {
title.text = currentItem.title
numberPicker.progress = currentItem.quantity
color.setCardBackgroundColor(android.graphics.Color.parseColor(currentItem.color))
colorName.text = currentItem.color_name
price.text =
doubleToStringNoDecimal((currentItem.price * currentItem.quantity).toDouble())
Glide.with(context)
.asBitmap()
.load(currentItem.url)
.into(productImage)
holder.binding.apply {
numberPicker.doOnProgressChanged { numberPicker, progress, formUser ->
listener.onPickerProgressChanged(
numberPicker,
progress,
formUser,
position
)
price.text =
doubleToStringNoDecimal((currentItem.price * progress).toDouble())
}
delete.setOnClickListener {
listener.delete(holder.adapterPosition)
removeItem(holder.adapterPosition, holder)
}
}
}
}
override fun getItemCount(): Int = list.size
fun doubleToStringNoDecimal(d: Double): String? {
val formatter: DecimalFormat = NumberFormat.getInstance(Locale.US) as DecimalFormat
formatter.applyPattern("#,###,###,###")
return formatter.format(d)
}
fun removeItem(position: Int, viewHolder: RecyclerView.ViewHolder) {
val removedItem = list[position]
val removedPosition = position
list.removeAt(position)
notifyItemRemoved(position)
val snackbar = Snackbar.make(
viewHolder.itemView,
"این کالا از سبد خرید حذف شد",
Snackbar.LENGTH_LONG
)
snackbar.setAction("بازگرداندن") {
list.add(removedPosition, removedItem)
notifyItemInserted(removedPosition)
listener.SnackActionClicked(position)
}
snackbar.setActionTextColor(Color.YELLOW);
snackbar.show();
}
interface ButtonListener {
fun onPickerProgressChanged(
numberPicker: NumberPicker,
progress: Int,
fromUser: Boolean,
position: Int
)
fun delete(position: Int)
fun SnackActionClicked(position: Int)
}
}
adapter =
BasketRecyclerAdapter(
items as ArrayList<Model.BasketItem>,
object : BasketRecyclerAdapter.ButtonListener {
override fun onPickerProgressChanged(
numberPicker: NumberPicker,
progress: Int,
fromUser: Boolean,
position: Int
) {
val currentitem = items[position]
viewModel.AddToCart(
localStore.getMobile().toString(),
currentitem.category,
currentitem.title,
currentitem.url,
currentitem.price,
progress,
currentitem.color,
currentitem.color_name,
currentitem.product_id
)
updateWorkerData(
currentitem.title,
currentitem.color,
Model.BasketItem::quantity,
progress
)
viewModel.CalculateTotalPrice(items)
.observe(viewLifecycleOwner) {
binding.price.text = doubleToStringNoDecimal(it)
}
}
override fun delete(position: Int) {
val currentitem = items[position]
viewModel.DeleteItemInCart(
localStore.getMobile().toString(),
currentitem.title,
currentitem.color_name
)
itemList.remove(
Model.BasketItem(
currentitem.id,
localStore.getMobile().toString(),
currentitem.category,
currentitem.title,
currentitem.url,
currentitem.price,
currentitem.quantity,
currentitem.color,
currentitem.color_name,
currentitem.product_id
)
)
if (items.size == 1)
if (isLastVisible()) {
basketpic.visibility = View.VISIBLE
emptyBasketText.visibility = View.VISIBLE
} else {
basketpic.visibility = View.GONE
emptyBasketText.visibility = View.GONE
}
viewModel.CalculateTotalPrice(items)
.observe(viewLifecycleOwner) {
binding.price.text = doubleToStringNoDecimal(it)
}
}
override fun SnackActionClicked(position: Int) {
val currentitem = items[position]
viewModel.AddToCart(
localStore.getMobile().toString(),
currentitem.category,
currentitem.title,
currentitem.url,
currentitem.price,
currentitem.quantity,
currentitem.color,
currentitem.color_name,
currentitem.product_id
)
binding.apply {
basketpic.visibility = View.GONE
emptyBasketText.visibility = View.GONE
}
viewModel.CalculateTotalPrice(items)
.observe(viewLifecycleOwner) {
binding.price.text = doubleToStringNoDecimal(it)
}
}
})
any help will be appreciated
UPDATE
you can see that first one is white and the second is brown but when i delete and undodelete the brown then white and reopen the fragment their position changes-> see second picture
after delete and undo deleteitems(first brown then white) and reopening the fragment
The Problem was that when i Clicked on Delete button the corresponding row in the Mysql was deleted and when i Clicked on Undo button the items that i deleted them
Were added to the table with new id and beacause of this the position of item changed after the fragment reopened
so i set a Snackbar.Callback to snackbar and i said that when it closed on its own then you can delete the item from database(mysql)
this is the code:
val snackbar = Snackbar.make(
viewHolder.itemView,
"این کالا از سبد خرید حذف شد",
Snackbar.LENGTH_LONG
)
snackbar.setAction("بازگرداندن") {
list.add(removedPosition, removedItem)
listener.SnackActionClicked(position)
notifyItemInserted(removedPosition)
}
snackbar.setActionTextColor(Color.YELLOW);
snackbar.addCallback(object : Snackbar.Callback() {
override fun onDismissed(snackbar: Snackbar?, event: Int) {
super.onDismissed(snackbar, event)
if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
// Snackbar closed on its own
// Delete item from mysql database
}
}
override fun onShown(snackbar: Snackbar?) {
super.onShown(snackbar)
}
});
snackbar.show();

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?

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

RecyclerView changing image incorrectly onNotifyItemChanged

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".

Categories

Resources