RecyclerView 用法及缓存原理及性能优化

image.png

总的来说,RecyclerView只是负责滚动显示的功能,Adapter才决定内容,MainActivity中使用 LayoutManagers来决定RecyclerView的布局样式(线性,网格,瀑布流,滚动方向)

用法

1.将 RecyclerView 添加到布局中



    


2.创建一个item.xml文件作为显示的子项

3.为 RecyclerView 实现 Adapter

1.为 Adapter 创建一个新类,例如 ItemAdapter。

class ItemAdapter(private val context: Context, private val dataset: List) {

}

2.创建用于代表单个列表项视图的自定义 ViewHolder 类(ItemViewHolder)。从 RecyclerView.ViewHolder 类进行扩展。

class ItemAdapter(private val context: Context, private val dataset: List) {

    class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.findViewById(R.id.item_title)
    }
}

3.修改 ItemAdapter 类,以便从 RecyclerView.Adapter 类通过自定义 ViewHolder 类进行扩展。

class ItemAdapter(
    private val context: Context,
    private val dataset: List
) : RecyclerView.Adapter() {

    class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.findViewById(R.id.item_title)
    }
}

4.在 Adapter 内实现以下方法:getItemsCount()、onCreateViewHolder() 和 onBindViewHolder()。

override fun getItemCount(): Int {
    return dataset.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
    // create a new view
    val adapterLayout = LayoutInflater.from(parent.context)
        .inflate(R.layout.list_item, parent, false)

    return ItemViewHolder(adapterLayout)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
    val item = dataset[position]
    holder.textView.text =  context.resources.getString(item.stringResourceId)
}

4.修改 MainActivity 以使用 RecyclerView(使用了ViewBinding)

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val myDataset = Datasource().loadAffirmations()

        binding.recyclerView.adapter = ItemAdapter(this,myDataset)
        binding.recyclerView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)
        binding.recyclerView.setHasFixedSize(true)

//实现翻页效果
LinearSnapHelper().attachToRecyclerView(binding.recyclerView)
    }
}

在ViewBinding中使用

class TypeAdapter: RecyclerView.Adapter() {
    private val typeList = listOf("main course",
            "side dish",
            "dessert",
            "appetizer",
            "salad",
            "bread",
            "breakfast",
            "soup",
            "beverage",
            "sauce",
            "marinade",
            "fingerfood",
            "snack",
            "drink")

    class ItemViewHolder(binding: TypeItemBinding): RecyclerView.ViewHolder(binding.root){
        val titleTextView: TextView = binding.titleText
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        val adapterLayout = LayoutInflater.from(parent.context)
        return ItemViewHolder(TypeItemBinding.inflate(adapterLayout))
    }

    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = typeList[position]
        holder.titleTextView.text = item
    }

    override fun getItemCount(): Int {
        return typeList.size
    }
}
class RecipeFragment : Fragment() {
    private lateinit var binding: FragmentRecipeBinding

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        binding = FragmentRecipeBinding.inflate(inflater)

        //recyclerView
        binding.typeRecyclerView.layoutManager = LinearLayoutManager(requireContext(),RecyclerView.HORIZONTAL,false)
        binding.typeRecyclerView.adapter = TypeAdapter()
        return binding.root
    }

}

tips:

RecyclerView 微件可帮助您显示数据列表。
RecyclerView 使用 Adapter 模式来调整和显示数据。
ViewHolder 为 RecyclerView 创建并存储视图。
一个 ViewHolder 代表一个列表项视图
RecyclerView 附带内置 LayoutManagers。RecyclerView 将列表项的布局工作委托给 LayoutManagers。

RecyclerView的缓存机制

发现了一篇很好的文章:
https://www.jianshu.com/p/f9e21269da26
简单来说就是Recyclerview在获取ViewHolder时在Scrap(屏幕内的item)和Cache(屏幕外前后的几个item)通过Position寻找缓存,然后是ViewCacheExtension中自己定义的缓存,此时无需重新绑定数据;若没有找到则在RecycledViewPool中通过ViewType寻找缓存,找到后的数据是脏数据,需通过onBindViewHolder重新绑定数据。
通过onViewAttachedToWindow()方法获取item的关注次数

RecyclerView的性能优化

1.在onCreateViewHolder里设置点击按钮事件

达到一个view对应一个viewHolder对应一个onClickListener

2.使用LinearLayout.setInitialPrefetchItemCount()

当嵌套使用RecyclerView时(比如一个竖向的RecyclerView的itemView是一个横向的RecyclerView)使用LinearLayout.setInitialPrefetchItemCount()
(只有RecyclerView嵌套时并且LinearLayout能用这个api),进行预渲染横向列表初次显示时可见的item个数。

3.使用RecyclerView.setHasFixedSize()

image.png

4.多个RecyclerView共用一个RecycledViewPool

        val recycledViewPool = RecyclerView.RecycledViewPool()
        binding.recyclerView1.setRecycledViewPool(recycledViewPool)
        binding.recyclerView2.setRecycledViewPool(recycledViewPool)
        binding.recyclerView3.setRecycledViewPool(recycledViewPool)

5.DiffUtil

见博客:https://blog.csdn.net/zxt0601/article/details/52562770

ItemDecoration的用处

1.画分割线:DividerItemDecoration
2.高亮item
3.item分组

你可能感兴趣的:(RecyclerView 用法及缓存原理及性能优化)