简体   繁体   中英

recyclerView won't scroll smoothly for first time

I have a recyclerView inside a fragment, this fragment is located in a viewpager2.

I read data from server and convert them to my ModelClass, them create an ArrayList and pas this array list to recyclerView. here is my recyclerView item layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:background="@drawable/main_icon_background"
    android:elevation="5dp"
    android:layoutDirection="rtl"
    android:orientation="horizontal"
    android:padding="10dp">


    <ImageView
        android:id="@+id/image"
        android:layout_width="120dp"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@color/black" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="0.6"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:ellipsize="end"
            android:maxLines="1"
            android:textAppearance="@style/vazir_font"
            android:textColor="@color/black" />

        <TextView
            android:id="@+id/description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:ellipsize="end"
            android:maxLines="3"
            android:textAppearance="@style/vazir_font"
            android:textColor="@color/gray"
            android:textSize="13sp" />


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="1.5dp"
            android:layout_marginStart="20dp"
            android:layout_marginTop="5dp"
            android:layout_marginEnd="20dp"
            android:layout_marginBottom="8dp"
            android:alpha="0.5"
            android:background="@color/gray" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/source"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginEnd="10dp"
                android:layout_weight="0.8"
                android:ellipsize="end"
                android:maxLines="1"
                android:textAppearance="@style/vazir_font"
                android:textColor="@color/colorPrimaryDark"
                android:textSize="13sp" />

            <TextView
                android:id="@+id/date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:gravity="end"
                android:textAppearance="@style/vazir_font"
                android:textColor="@color/colorAccent"
                android:textSize="13sp" />

        </LinearLayout>


    </LinearLayout>


</LinearLayout>

and here is my recyclerView adapter:

class NewsRecyclerViewAdapter : RecyclerView.Adapter<NewsRecyclerViewAdapter.ViewHolder>() {

    private val items = ArrayList<NewsAdapterModel>()
    lateinit var onClick: NewsTutorialClickListener

    fun add(list: ArrayList<NewsAdapterModel>) {
        items.clear()
        items.addAll(list)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view =
            LayoutInflater.from(parent.context).inflate(R.layout.news_recycler_model, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int = items.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.binding(items[position])
    }

    override fun getItemId(position: Int): Long {
        return items[position].id.hashCode().toLong()
    }


    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun binding(model: NewsAdapterModel) {


            itemView.setOnClickListener {
                onClick.onClick(model.id)
            }


            itemView.title.text = model.title
            itemView.description.text = model.description
            itemView.date.text = Arrange().persianConverter(model.date)
            itemView.source.text = model.source

            Glide.with(itemView.context)
                .load(model.image)
                .placeholder(R.mipmap.logo)
                .into(itemView.image)

        }
    }

}

I used this recycler view in my fragment just like this:

 override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        adapter.onClick = this
        binding.recyclerView.layoutManager = LinearLayoutManager(context)
        binding.recyclerView.adapter = adapter
        binding.recyclerView.setHasFixedSize(true)
        binding.recyclerView.setItemViewCacheSize(20)


        scope.launch {
            withContext(Dispatchers.Default) {
                fetchNews()
            }
        }
    }

my problem is: when I scroll recycler view for first time it is not smooth and it seems some frames are jumped, but when I reach end of recyclerView and scroll to up then scroll down it is very smooth and find. how can I solve this issue? I also should mention that Items of recyclerView are not much, it's around 10 items.

remove

 recyclerView.setHasFixedSize(true)

actually it can cause no harm and indeed improves performance, because recyclerView won't bother calculating size of viewHolders evrytime inside onBindViewHolder . But you have all your TextViews with wrap_content height which will most certainly cause some broken UI in future.


remove

recyclerView.setItemViewCacheSize(20)

This function forces RecyclerView to prematurely inflate and bind 20 extra ViewHolders , so that it can use them straight away without calling OncreateViewHolder and OnBindViewHolder . You should'nt play around with this and just go with the defaults. Although 20 extra viewholders shouldn't have been a big deal, i guess maybe RecyclerView got confused because you forced it create extra 20 on top of existing 10 , while you list only contains 10 items. It was taking time to create those extra viewHolders blocking ui thread, but after they were created it seemed smooth.

You don't need to add these lines

        binding.recyclerView.setHasFixedSize(true)
        binding.recyclerView.setItemViewCacheSize(20)

Please remove these lines

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM