当前位置:网站首页>Efficient use of RecyclerView Section 2
Efficient use of RecyclerView Section 2
2022-07-31 14:57:00 【[email protected]】
Lists are used the most in development,But performance is also probably the most overlooked part,在做性能优化时,We all know that when writing layouts, try to use Constraint Layout as much as possible,减少布局的嵌套层次,Reduce redundant backgrounds to improve layout parsing rendering speed,But that's just one point of optimization.Next, refer to the official oneAPICombined with the actual scene to further optimize the list-related.
一,DiffUtilDifferentiated refresh
相较于ListView,RecyclerViewLocal refresh is supported,Greatly improved performance when refreshing,但平时开发中,Most people do it for simplicity or being lazy,直接调用了RecyclerView的全局刷新,After all, you only need to write one line of code,Nothing will go wrong either,But when doing performance optimization,如果想更近一步,我们可以结合DiffUtilDo a differential refresh.
如下:
1,创建xml布局
1)Activity布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<androidx.appcompat.widget.AppCompatButton app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintHorizontal_weight="1" app:layout_constraintRight_toLeftOf="@+id/btn_loadMore" android:id="@+id/btn_refresh" android:text="refresh" android:gravity="center" android:layout_width="0dp" android:layout_height="wrap_content"/>
<androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_study" android:layout_width="match_parent" app:layout_constraintTop_toBottomOf="@+id/btn_refresh" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" android:orientation="vertical" tools:listitem="@layout/item_study" app:layout_constraintBottom_toBottomOf="parent" android:layout_height="0dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2) item布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp" xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.appcompat.widget.AppCompatImageView android:id="@+id/iv_icon" android:layout_width="48dp" app:layout_constraintLeft_toLeftOf="parent" android:src="@mipmap/ic_launcher" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:layout_height="48dp"/>
<TextView app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toRightOf="@+id/iv_icon" android:layout_width="wrap_content" android:id="@+id/tv_title" android:gravity="center" android:text="Study" android:textSize="22sp" android:layout_marginLeft="16dp" app:layout_constraintVertical_chainStyle="packed" app:layout_constraintBottom_toTopOf="@+id/tv_second" android:textColor="@android:color/black" android:layout_height="wrap_content"/>
<TextView android:id="@+id/tv_subtitle" android:layout_width="wrap_content" app:layout_constraintLeft_toRightOf="@+id/iv_icon" app:layout_constraintTop_toBottomOf="@+id/tv_study" android:textSize="16sp" android:layout_marginLeft="16dp" app:layout_constraintVertical_chainStyle="packed" android:text="zhansan" android:textColor="@color/cardview_dark_background" app:layout_constraintBottom_toBottomOf="parent" android:layout_height="wrap_content"/>
<TextView android:id="@+id/tv_gender" android:layout_width="wrap_content" android:textSize="18sp" android:text="男" android:textColor="@color/material_on_surface_emphasis_high_type" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="parent" android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2,继承ListAdapter
package com.example.recyclerviewstudy.two
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SortedList
import com.example.recyclerviewstudy.R
import com.example.recyclerviewstudy.StudentInfo
class StudentAdapter:ListAdapter<StudentInfo, StudentAdapter.ViewHolder>(StudentDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_study,parent,false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position))
}
class ViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
val tv_name: TextView = itemView.findViewById(R.id.tv_title)
val tv_age: TextView = itemView.findViewById(R.id.tv_subtitle)
val tv_gender:TextView = itemView.findViewById(R.id.tv_gender)
fun bind(entity:StudentInfo){
entity.apply {
tv_name.text = name
tv_age.text = "$age"
tv_gender.text = gender
}
}
}
}
//核心函数
class StudentDiffCallback:DiffUtil.ItemCallback<StudentInfo>(){
override fun areItemsTheSame(oldItem: StudentInfo, newItem: StudentInfo): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: StudentInfo, newItem: StudentInfo): Boolean {
return oldItem == newItem
}
}
Adapter中核心就两点:
1)继承ListAdapter
2)实现DiffUtil.ItemCallback,判断两个对象是否相同
3,Activity中初始化RecyclerView及Adapter
//学生数据列表
private val studentEntities = ArrayList<StudentInfo>()
//适配器
private val studentAdapter by lazy {
StudentAdapter()
}
初始化Adapter
val rv_student = findViewById<RecyclerView>(R.id.rv_student)
rv_student.adapter = studentAdapter
更新数据时
studentAdapter.submitList(studentEntities)
When the request interface is successful,直接调用submitList进行数据更新,Give it a refreshDiffUtil内部自行处理.
There are also certain limitations in using scenarios in this way,Suitable for list fixed,If you want to support the pull-down refresh type,需要基于DiffUtil.Callback进行实现
例如:
/**
* getOldListSize():旧数据集的长度.
getNewListSize():新数据集的长度
areItemsTheSame():判断是否是同一个Item.
areContentsTheSame():If it is a passItem,此方法用于判断是否同一个 Item 的内容也相同
*/
private fun diffCallBack(oldDataSource:ArrayList<StudentInfo>,
newDataSource:ArrayList<StudentInfo>) =
object :DiffUtil.Callback(){
override fun getOldListSize() = oldDataSource.size
override fun getNewListSize() = newDataSource.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldDataSource[oldItemPosition].name == newDataSource[newItemPosition].name
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
if (oldDataSource[oldItemPosition].name != newDataSource[newItemPosition].name||
oldDataSource[oldItemPosition].age == newDataSource[newItemPosition].age){
return false
}
return true
}
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
return super.getChangePayload(oldItemPosition, newItemPosition)
}
}
DiffUtilThe difference algorithm is used internally,Differentiated objects are calculated,然后调用RecyclerView的insert,deleteWait for the function to perform a local refresh,Improve refresh efficiency.
二,AsyncListDiffer Asynchronous differential refresh
DiffUtilCan solve the local refresh problem,但也存在缺陷,当数据量大时,会卡主线程,Its data comparison is carried out on the main thread,所以当数据量大时,则推荐使用AsyncListDifferPerform an asynchronous differential comparison refresh,提升性能.
相对于DiffUtilThe difference in usage is mainly reflected in Adapter上,详见如下代码 :
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.recyclerviewstudy.R
import com.example.recyclerviewstudy.StudentInfo
class AsyncStudentAdapter:RecyclerView.Adapter<AsyncStudentAdapter.ViewHolder>() {
//创建AsyncListDiffer对象,传入DiffUtil.ItemCallback
private val mDiffer = AsyncListDiffer(this,StudentDiffCallback())
fun submit(list:List<StudentInfo>){
mDiffer.submitList(list)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.item_study, parent, false)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(mDiffer.currentList[position])
}
override fun getItemCount() = mDiffer.currentList.size
class ViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
val tv_name: TextView = itemView.findViewById(R.id.tv_title)
val tv_age: TextView = itemView.findViewById(R.id.tv_subtitle)
val tv_gender: TextView = itemView.findViewById(R.id.tv_gender)
fun bind(entity: StudentInfo){
entity.apply {
tv_name.text = name
tv_age.text = "$age"
tv_gender.text = gender
}
}
}
class StudentDiffCallback: DiffUtil.ItemCallback<StudentInfo>(){
override fun areItemsTheSame(oldItem: StudentInfo, newItem: StudentInfo): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: StudentInfo, newItem: StudentInfo): Boolean {
return oldItem == newItem
}
}
}
其核心步骤如下:
1)实现 StudentDiffCallbackIn it, define the differentiation of the object entity.
2)创建AsyncListDiffer对象,传入DiffUtil.ItemCallback对象
3)定义一个submit函数,For refreshing external data
在使用时,直接调用adapter的submitRefresh the data list.
三,SortedListQuickly sort the list
In some cases when we need to sort the data list,很多人想到的是,Iterate through the comparison and sort one by one,效率低下,When encountering a large amount of data,long time condition,If it is not handled properly, there will be many problems,如果使用SortedListThis greatly improves the sorting efficiency,It also makes the code logic more clear.
The concrete example is also based on the starting layout problem,核心代码主要在Adapter中,如下:
class TeacherAdapter:RecyclerView.Adapter<TeacherAdapter.ViewHolder>() {
//核心点
private val sortedList by lazy {
SortedList(TeacherInfo::class.java,sortListCallback(this))
}
fun submit(list:List<TeacherInfo>){
sortedList.beginBatchedUpdates()
sortedList.addAll(list)
sortedList.endBatchedUpdates()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_study,parent,false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(sortedList.get(position))
}
override fun getItemCount() = sortedList.size()
class ViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
val tv_name: TextView = itemView.findViewById(R.id.tv_title)
val tv_age: TextView = itemView.findViewById(R.id.tv_subtitle)
val tv_gender: TextView = itemView.findViewById(R.id.tv_gender)
fun bind(entity: TeacherInfo){
entity.apply {
tv_name.text = name
tv_age.text = "$age"
tv_gender.text = gender
}
}
}
//继承SortedListAdapterCallback定义排序规则
class sortListCallback(adapter:RecyclerView.Adapter<*>):
SortedListAdapterCallback<TeacherInfo>(adapter){
//用来排序
override fun compare(o1: TeacherInfo, o2: TeacherInfo): Int {
return o1.id.compareTo(o2.id)
}
override fun areContentsTheSame(oldItem: TeacherInfo, newItem: TeacherInfo): Boolean {
return oldItem.hashCode() == newItem.hashCode()
}
override fun areItemsTheSame(item1: TeacherInfo, item2: TeacherInfo): Boolean {
return item1.id == item2.id
}
}
}
如上便是SortedList的核心代码,在使用时,直接submitRefresh the data,Of course, it also provides a lot of inserting a single data or deleting a single dataapi,更多的用法参考官方API文档
四,ConcatAdapter连接多个Adapter
When a page consists of multiple different categories,可以使用ConcatAdapter进行Adapter拼接,但其也存在一定的局限性,Because the same one is usedRecyclerView,So its list layout direction must be consistent,The usage is also very simple and straightforward to createConcatAdapter对象,传入相应的Adapter即可
val rv_student = findViewById<RecyclerView>(R.id.rv_student)
val concatAdapter = ConcatAdapter(studentAdapter, asyncStudentAdapter)
rv_student.adapter = concatAdapter
关键RecyclerView的使用,This concludes the second chapter.The example security in the text is for reference only,It can be expanded according to actual needs during development,Please advise if there are mistakes or more efficient usage.
版权声明
本文为[[email protected]]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/212/202207311451011572.html
边栏推荐
- Small test knife: Go reflection helped me convert Excel to Struct
- NPM Taobao mirror (latest version) released a new version of npm mirror at 2021-11-21 16:53:52 [easy to understand]
- Detailed guide to compare two tables using natural full join in SQL
- SetoolKit User Guide
- C language basic practice (nine-nine multiplication table) and printing different asterisk patterns
- R语言ggplot2可视化:使用ggpubr包的ggboxplot函数可视化分组箱图、使用ggpar函数改变图形化参数(legend、修改可视化图像的图例在整图中的位置)
- TCP详解
- 【CUDA学习笔记】初识CUDA
- Getting started with UnityShader (3) - Unity's Shader
- I summed up the bad MySQL interview questions
猜你喜欢

Uniapp WeChat small application reference standard components
![Recommendation System - Recall Phase - 2013: DSSM (Twin Towers Model) [Embedding (Semantic Vector) Recall] [Microsoft]](/img/40/b567780ed2cf04f1f1336922816f86.png)
Recommendation System - Recall Phase - 2013: DSSM (Twin Towers Model) [Embedding (Semantic Vector) Recall] [Microsoft]

DBeaver连接MySQL 8.x时Public Key Retrieval is not allowed 错误解决

TRACE32——C源码关联

The recently popular domestic interface artifact Apipost experience

Word表格转到Excel中

2021 OWASP TOP 10 Vulnerability Guide

五个维度着手MySQL的优化

AVH部署实践 (一) | 在Arm虚拟硬件上部署飞桨模型

Small test knife: Go reflection helped me convert Excel to Struct
随机推荐
TCP详解
Word表格转到Excel中
49. The copy constructor and overloaded 】
Redis与分布式:主从复制
名创优品斥资6.95亿购买创始人叶国富所持办公楼股权
The 232-layer 3D flash memory chip is here: the single-chip capacity is 2TB, and the transmission speed is increased by 50%
435. 无重叠区间
常用工具命令速查表
OAuth2:使用JWT令牌
为什么要分库分表?
Unity Shader入门精要学习——透明效果
R语言计算时间序列数据的移动平均值(滚动平均值、例如5日均线、10日均线等):使用zoo包中的rollmean函数计算k个周期移动平均值
力扣:738.单调递增的数字
Combination series - there are combinations when there are arrangements
【CUDA学习笔记】初识CUDA
OAuth2:单点登陆客户端
Network cable RJ45 interface pins [easy to understand]
thread_local 变量的析构顺序
PDF 拆分/合并
OpenShift 4 - Deploy Redis Cluster with Operator