• RecyclerView的高效使用


    在开发的过程中列表相关的布局是最不可或缺的一部分,而掌握一些高效的技巧可以帮助我们提升开发效率的同时,还能优化代码,减少冗余和bug的产生。

    1.listitem实时预览

    在UI绘制时,免不了进行细节和样式的调整,如果每次的调整都去run之后查看效果,则效率低下,使用listitem,则可以避免运行,直接使用AndroidStudio自带的预览功能进行调试
    例如

    <androidx.recyclerview.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rv_student"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:listitem="@layout/item_study"
        tools:context=".one.StudentActivity" />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    效果如下:
    在这里插入图片描述

    2,xml中设置layoutManager

    <androidx.recyclerview.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rv_student"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:listitem="@layout/item_study"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        tools:context=".one.StudentActivity" />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在布局代码中可以直接设置LayoutManager类型和相关的一些属性,例如方向,网格布局时每一行的个数等。

    3,使用默认的分割线

    可以使用官方提供的默认的分割线样式,减少重复的创建。

        //添加默认的分割线
            rv_student.addItemDecoration(DividerItemDecoration(this,
                (rv_student.layoutManager as LinearLayoutManager).orientation))
    
    • 1
    • 2
    • 3

    如需个性化定制,需要自己基于ItemDecoration进行定制

    4,添加Item点击事件

    使用Kotlin函数式的思想,快捷的添加点击事件
    1)在Adapter的构造函数中添加入参

    class StudentAdapter(private val data:ArrayList<StudentInfo>,
                         private val itemClick:(StudentInfo) ->Unit):
        RecyclerView.Adapter<StudentAdapter.ViewHolder>() {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)初始化Adapter时传入点击的函数

        //学生数据列表
        private val studentEntities = ArrayList<StudentInfo>()
        //适配器
        private val  studentAdapter by lazy {
            StudentAdapter(studentEntities,this::onStudentItemClick)
        }
    
    	/**
    	*点击事件
    	*/
        private fun onStudentItemClick(entity:StudentInfo){
            /**
             * 点击Item时,获取的当前点击的用户信息
             */
            Log.d(TAG,"onStudentItemClick()--->$entity")
            Toast.makeText(this,"$entity",Toast.LENGTH_LONG).show()
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3)使用时

      itemView.setOnClickListener { itemClick(entity) }
    
    • 1

    5,Adapter中获取上下文

    在onCreateViewHolder中获取context对象,减少构建时的传参

      //定义上下文
        private lateinit var context:Context
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            context = parent.context
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如上功能完成的代码如下:
    1,item布局

    
    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    2,Activity布局

    
    <androidx.recyclerview.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rv_student"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:listitem="@layout/item_study"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        tools:context=".one.StudentActivity" />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3,Activity代码

    package com.example.recyclerviewstudy.one
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.util.Log
    import android.widget.Toast
    import androidx.recyclerview.widget.DividerItemDecoration
    import androidx.recyclerview.widget.LinearLayoutManager
    import androidx.recyclerview.widget.RecyclerView
    import com.example.recyclerviewstudy.R
    import com.example.recyclerviewstudy.StudentInfo
    
    class StudentActivity : AppCompatActivity() {
        companion object{
            val TAG = this::class.simpleName
        }
        //学生数据列表
        private val studentEntities = ArrayList<StudentInfo>()
        //适配器
        private val  studentAdapter by lazy {
            StudentAdapter(studentEntities,this::onStudentItemClick)
        }
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_study)
            initRecyclerView()
        }
    
        private fun initRecyclerView(){
            val rv_student = findViewById<RecyclerView>(R.id.rv_student)
            //添加默认的分割线
            rv_student.addItemDecoration(DividerItemDecoration(this,
                (rv_student.layoutManager as LinearLayoutManager).orientation))
            rv_student.adapter = studentAdapter
            produceData()
        }
    
        private fun onStudentItemClick(entity:StudentInfo){
            /**
             * 点击Item时,获取的当前点击的用户信息
             */
            Log.d(TAG,"onStudentItemClick()--->$entity")
            Toast.makeText(this,"$entity",Toast.LENGTH_LONG).show()
        }
    	
    	//生产数据
        private fun produceData(){
            for (i in 0..20){
                studentEntities.add(StudentInfo("zhang san $i",i,if (i%2==0)"男" else "女"))
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    4,Adapter完整代码

    package com.example.recyclerviewstudy.one
    
    import android.content.Context
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.TextView
    import androidx.recyclerview.widget.RecyclerView
    import com.example.recyclerviewstudy.R
    import com.example.recyclerviewstudy.StudentInfo
    
    class StudentAdapter(private val data:ArrayList<StudentInfo>,
                         private val itemClick:(StudentInfo) ->Unit):
        RecyclerView.Adapter<StudentAdapter.ViewHolder>() {
    
        //定义上下文
        private lateinit var context:Context
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            context = parent.context
            return ViewHolder(LayoutInflater.from(context)
                .inflate(R.layout.item_study,parent,false),itemClick)
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.bind(data[position])
        }
    
        override fun getItemCount() = data.size
    
        inner class ViewHolder(itemView:View,val itemClick:(StudentInfo) -> Unit):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)
            private lateinit var entity:StudentInfo
    
            init {
                itemView.setOnClickListener { itemClick(entity) }
            }
    
            fun bind(entity:StudentInfo){
                this.entity = entity
                entity.apply {
                    tv_name.text = name
                    tv_age.text = "$age"
                    tv_gender.text = gander
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    针对RecyclerView相关的实际使用目前学到的就这些,具体实践还需结合自己项目架构进行优化实现。
    RecyclerView是开发中必不可少的,虽然它的功能和性能相较于ListView有了很大的改善和提升,但使用不当还是会存在一些性能问题,且目还有进一步的优化空间,结合mCacheViewExtension和DiffUtil的实现,让你的UI更加流畅。

  • 相关阅读:
    Python基础之列表,元组,字典,集合,推导式,迭代器
    Metasequoia 4 水杉3D建模工具 附序列号
    第二章 Caché 服务器页面简介 - 你应该知道
    【蜂鸟E203内核解析】Chap.3 自定义指令与协处理器设计
    css 流式布局 九宫格布局
    python自动化测试面试题(三)(持续更新)
    Java直接量(字面量)及 Java运算符优先级
    Numpy使用
    Linux安装MySQL
    强化学习 DQN 经验回放 是什么
  • 原文地址:https://blog.csdn.net/zdc9023/article/details/125998038