Ấu Khương Duy
Ấu Khương Duy

Reputation: 53

RecyclerView Scrolling problem with complexity item

I facing laggy scrolling issue with complexity item. I trying to build a view like this image below. Many more item like this

I tried to #setHasStableIds #hasFixedSize #PreCacheLinearLayout #setItemViewCacheSize ... A lot of way but it still lagging. I know may be my item is too complexity but this is requirements :( If you have some ideas to resolve this problem, please help me! Thank so much <3

My adapter is multiple view type. Using Databinding, MVVM. This RecyclerView also below AppBarLayout in CoordinatorLayout.

RecyclerView:

            android:id="@+id/rvHome"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorGrayLight"
            android:clipToPadding="false"
            app:items="@{viewModel.listData}"
            android:nestedScrollingEnabled="true"
            android:orientation="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

Binding Adapter:

        @BindingAdapter("items")
        fun<T> setItems(view: RecyclerView, model: ObservableArrayList<T>?) {
            model?.let {
                if(view.adapter is BaseRecyclerViewAdapter<*>){
                    (view.adapter as BaseRecyclerViewAdapter<T>).listItem  = it;
                }
            }
        }

Base Adapter:

abstract class BaseRecyclerViewAdapter<T>() :
    RecyclerView.Adapter<BindingViewHolder>() {

    var listItem: ObservableArrayList<T>? = null
        set(value) {
            value?.let {
                onSettingListItem(it);
            }
            field = value
            value?.let {
                it.addOnListChangedCallback(onListChangedCallback)
            }
            notifyDataSetChanged()
        }

    var presenter: Presenter? = null
    var decorator: Decorator? = null

    fun add(t:T){
        listItem?.let {
            it.add(t)
            notifyDataSetChanged()
        }
    }
    fun addAll(items:Collection<T>){
        Log.d("TAG","data $items")
        Log.d("TAG","data $listItem")
        listItem?.let {
            it.addAll(items)
            notifyDataSetChanged()
        }
    }
    open fun onSettingListItem(list: ObservableArrayList<T>) {

    }

    val onListChangedCallback = object : ObservableList.OnListChangedCallback<ObservableList<T>>() {
        override fun onChanged(sender: ObservableList<T>) {
            notifyDataSetChanged()
        }

        override fun onItemRangeChanged(
            sender: ObservableList<T>,
            positionStart: Int,
            itemCount: Int
        ) {
            notifyItemRangeChanged(positionStart, itemCount)
        }

        override fun onItemRangeInserted(
            sender: ObservableList<T>,
            positionStart: Int,
            itemCount: Int
        ) {
            notifyItemRangeInserted(positionStart, itemCount)
        }

        override fun onItemRangeMoved(
            sender: ObservableList<T>,
            fromPosition: Int,
            toPosition: Int,
            itemCount: Int
        ) {
            notifyItemMoved(fromPosition, toPosition)
        }

        override fun onItemRangeRemoved(
            sender: ObservableList<T>,
            positionStart: Int,
            itemCount: Int
        ) {
            notifyItemRangeRemoved(positionStart, itemCount)
        }
    }



    override fun onBindViewHolder(holder: BindingViewHolder, position: Int) {
        listItem?.let {
            val item = it[position]
            // set item variable
            holder.binding.setVariable(BR.viewModel, item)
        }
        holder.binding.setVariable(BR.presenter, presenter)
//        holder.binding.setVariable(BR.currentPos, position)
        holder.binding.executePendingBindings()
        if (decorator != null) {
            decorator!!.decorate(holder, position, getItemViewType(position))
        }
    }

    override fun getItemCount(): Int {
        listItem?.let {
            return it.size
        }
        return 0;
    }

    interface Presenter {
        fun onItemClick(view: View, item: Any, position: Int)
    }

    interface Decorator {
        fun decorate(holder: BindingViewHolder, position: Int, viewType: Int)
    }


}

Chirld Item (2):

<androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view_trending_trip"
            style="@style/RecyclerHorizontalStyle"
            android:nestedScrollingEnabled="false"
            app:items="@{viewModel.data}"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            />

And many code, but similar above. Thank you so much!

Upvotes: 1

Views: 103

Answers (1)

satyan_android
satyan_android

Reputation: 364

Hi @Duy Pls use this method.. rv.getRecycledViewPool().setMaxRecycledViews(0, 0); it may be helpful.. see this link for method description..

Upvotes: 1

Related Questions