简单案例理清Adapter、ViewHolder和RecyclerView之间的关系

虽然ListView功能很强大,但是也有很多缺点。比如说性能差、扩展性不好等
为此,Android5.0之后提供了一个更强大的滚动控件——RecyclerView,可以说是一个增强版的ListView,优化了ListView的各种不足。
注:本文将以kotlin代码的方式编写,我会尽量写上注释,如有不懂可以提问!
今天先写一个简单的案例,目的在于理清关系;如后期有机会的话,再写一个万能的、多级联动的案例给大家。
案例之前先介绍一下各自的任务,以便理解:

RecyclerView:

用户滑动屏幕切换视图时,上一个视图会回收利用。主要任务是视图回收再利用,循环往复。

ViewHolder:

主要任务是容纳View视图。

Adapter:

从模型层获取数据,然后提供给RecyclerView显示。主要任务是创建ViewHolder和将模型层的数据绑定到ViewHolder上。

LayoutManager:

RecyclerView不会亲自摆放屏幕上的列表项,摆放列表项的任务被委托给了LayoutManager。主要任务是指定RecyclerView的布局方式。

1.添加依赖库

RecyclerView属于新增的控件,Android将RecyclerView定义在support库里。若要使用RecyclerView,第一步是要在build.gradle中添加对应的依赖库。既然要用kotlin代码去实现,那么还要添加kotlin的依赖库。打开app/build.gradle文件,在dependencies闭包中添加如下内容:

	implementation "androidx.core:core-ktx:+"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'androidx.cardview:cardview:1.0.0'

添加完之后记得Sync Now同步。

2.添加RecyclerView控件

在activity_main.xml中添加RecyclerView控件,并指定id,然后将宽度和高度都设置为match_parent,这样RecyclerView就沾满了整个布局的空间。代码如下:

	<?xml version="1.0" encoding="utf-8"?>
	<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

3.新建一个实体类,作为RecyclerView适配器的适配类型。新建Fruit类:

	class Fruit(val name:String, val imageId: Int) 

4.为RecyclerView的子项指定一个自定义布局

在layout目录下新建fruit_item.xml,代码如下:

	<?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"
	    xmlns:app="http://schemas.android.com/apk/res-auto">
	    <androidx.cardview.widget.CardView
	        android:layout_width="match_parent"
	        android:layout_height="60dp"
	        app:layout_constraintTop_toTopOf="parent">
	        <ImageView
	            android:id="@+id/fruitImage"
	            android:layout_width="40dp"
	            android:layout_height="40dp"
	            android:layout_gravity="center_vertical"
	            android:layout_marginLeft="10dp"/>
	        <TextView
	            android:id="@+id/fruitName"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_gravity="center_vertical"
	            android:layout_marginLeft="60dp"/>
	    </androidx.cardview.widget.CardView>
	</androidx.constraintlayout.widget.ConstraintLayout>

5.新建ViewHolder类

ViewHolder承载的是每一个列表项的视图,所以当使用RecyclerView的时候需要先对ViewHolder进行初始化定义。

	package com.example.myadapter.holder
	import android.view.View
	import android.widget.ImageView
	import android.widget.TextView
	import androidx.recyclerview.widget.RecyclerView
	import com.example.myadapter.R
	
	class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
	    
	    val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
	    val fruitName: TextView = view.findViewById(R.id.fruitName)
	    
	}

6.接下来为RecyclerView准备一个适配器,新建MyAdapter类,让这个适配器继承自RecyclerView.Adapter,并将泛型指定为ViewHolder

MyAdapter继承RecyclerView.Adapter必须重写onCreateViewHolder()、onBindViewHolder()和getItemCount()三个方法。

	package com.example.myadapter.adapter
	import android.view.LayoutInflater
	import android.view.View
	import android.view.ViewGroup
	import androidx.recyclerview.widget.RecyclerView
	import com.example.myadapter.Fruit
	import com.example.myadapter.R
	import com.example.myadapter.holder.ViewHolder
	
	class MyAdapter(private val fruitList: List<Fruit>) : RecyclerView.Adapter<ViewHolder>(){
		// 用于创建ViewHolder实例,并把加载的布局传入到构造函数去,再把ViewHolder实例返回
	    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
	        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.fruit_item, parent, false)
	        return ViewHolder(view)
	    }
		// 返回RecyclerView的子项数目
	    override fun getItemCount(): Int = fruitList.size
		// 将数据绑定在ViewHolder上,用于对子项的数据进行赋值,会在每个子项被滚动到屏幕内时执行
	    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
	    	// position得到当前项的Fruit实例
	        val fruit: Fruit = fruitList[position]
	        holder.fruitImage.setImageResource(fruit.imageId)
	        holder.fruitName.text = fruit.name
	    }
	} 

7.适配器准备好之后,我们就可以开始使用RecyclerView了

	package com.example.myadapter
	import android.os.Bundle
	import androidx.appcompat.app.AppCompatActivity
	import androidx.recyclerview.widget.LinearLayoutManager
	import com.example.myadapter.adapter.MyAdapter
	import kotlinx.android.synthetic.main.activity_main.*
	import java.util.ArrayList
	
	class MainActivity : AppCompatActivity(){
	    private val listFruit = ArrayList<Fruit>()
	    override fun onCreate(savedInstanceState: Bundle?) {
	        super.onCreate(savedInstanceState)
	        setContentView(R.layout.activity_main)
	        // 初始化水果数据
	        initFruits()
	        /* 1.获取RecyclerView对象
	           final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
	           kotlin可以直接在xml中调用控件ID,固此第一步可省略 */
	        // 2.创建线性布局管理器(默认是垂直方向)
	        val layoutManager = LinearLayoutManager(this)
	        // 3.为RecyclerView指定布局管理对象,此处就是直接调用RecyclerView控件的id:recyclerView
	        recyclerView.layoutManager = layoutManager
	        // 4.创建Adapter,并将水果数据listFruit传入到MyAdapter的构造函数中
	        val adapter = MyAdapter(listFruit)
	        // 5.填充Adapter,调用adapter方法完成适配器设置,这样RecyclerView和数据之间的关联就建立完成了
	        recyclerView.adapter = adapter
	    }
	    private fun initFruits() {
	        // repeat(times: Int)方法是重复执行代码块内容,参数代表执行的次数
	        repeat(2) {
	            listFruit.add(Fruit("Apple", R.drawable.apple_pic))
	            listFruit.add(Fruit("Banana", R.drawable.banana_pic))
	            listFruit.add(Fruit("Orange", R.drawable.orange_pic))
	            listFruit.add(Fruit("Watermelon", R.drawable.watermelon_pic))
	            listFruit.add(Fruit("Pear", R.drawable.pear_pic))
	            listFruit.add(Fruit("Grape", R.drawable.grape_pic))
	            listFruit.add(Fruit("Pineapple", R.drawable.pineapple_pic))
	            listFruit.add(Fruit("Strawberry", R.drawable.strawberry_pic))
	            listFruit.add(Fruit("Cherry", R.drawable.cherry_pic))
	            listFruit.add(Fruit("Mango", R.drawable.mango_pic))
	        }
	    }
	} 

8.运行程序,效果图如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值