首先,要明白RecyclerView是做什么的?其次是为什么要用RecyclerView?这里牵扯到RecyclerView和ListView的区别,这里不废话,大家自行百度即可!

以下示例我用的Android API 29 ,启用了AndroidX。

第一步,添加依赖

创建一个新的工程,在app/build.gradle中的dependencies闭包添加以下内容:

implementation 'com.android.support:appcompat-v7:29.0.0'

  注意这里的‘29.0.0’要和你的 compileSdkVersion 版本号一致。版本号是28,就改为28。

别的不需要改,以下是此时的项目目录以及gradle文件内容

第二步,创建RecyclerView布局

在你的布局文件中添加RecyclerView,切记要为RecyclerView添加id。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.recyclerview.widget.RecyclerView
android:id="@+id/rv_card"
android:layout_width="match_parent"
android:layout_height="match_parent"/> </RelativeLayout>

第三步,为RecyclerView中的item创建一个统一的布局文件

在layout下创建一个名为layout_rv_card的布局文件,文件名命名要和你的实际业务相匹配方便后期查找。

在此布局文件中,可以添加任何你想展示的视图,在这里我们先创建两个TextView为大家展示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:orientation="horizontal"> <TextView
android:id="@+id/tv_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" /> <TextView
android:id="@+id/tv_state"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
</LinearLayout>

  别忘了添加id。

第四步,创建Adapter

  Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带。

  如果之前没有接触过,先跟着做,做完之后就会理解了。

  我们在项目目录下新建一个Java类,取名为CardAdapter。

  然后在CardAdapter中我们创建一个内部类MyViewHolder继承RecyclerView.ViewHolder。

  为什么要创建内部类?

  答:就是为了方便而已,创建在外部也是可以,但是如果项目大了之后,类太多不好区分,而且基本上因为布局的不同ViewHolder也基本不同,不会复用,所以创建在内部即可。

  为什么要使用ViewHolder?

  答:ViewHolder的主要任务:容纳View视图。前边我们提到Adapter连接了后端数据和前端显示,viewHolder的作用就是提供前端的视图文件。

接下来,我们在ViewHolder绑定视图文件,同在activity中类似,itemView顾名思义即列表中每一项的视图,每一项都要绑定。

import android.view.View;
import android.widget.TextView; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; /**
* @Author: Messi Mei
* @Date: 2020/8/24 13:46
* @Email: 709909986@qq.com
**/
public class CardAdapter { class MyViewHolder extends RecyclerView.ViewHolder {
private TextView tvId,tvState;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
tvId = itemView.findViewById(R.id.tv_id);
tvState = itemView.findViewById(R.id.tv_state);
}
}
}

第五步,完成Adapter

在我们创建的CardAdapter类继承我们创建的内部类MyViewHolder,并重写提供的三个方法:

onCreateViewHolder(),onBindViewHolder(),getItemCount()
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; /**
* @Author: Messi Mei
* @Date: 2020/8/24 13:46
* @Email: 709909986@qq.com
**/
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.MyViewHolder> { @NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
} @Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { } @Override
public int getItemCount() {
return 0;
} class MyViewHolder extends RecyclerView.ViewHolder {
private TextView tvId,tvState;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
tvId = itemView.findViewById(R.id.tv_id);
tvState = itemView.findViewById(R.id.tv_state);
}
}
}

5.1重写onCreateViewHolder方法,返回我们的内部类MyViewHolder ,此处为将我们的item布局文件和adapter绑定。

 @NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.layout_rv_card,parent,false);
return new MyViewHolder(view);
}

也可以写为

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_rv_card,parent,false);
return new MyViewHolder(view);
}

一样的。

5.2为每一项视图,添加数据。

此处holder为你每一项的MyViewHolder对象,position 定位,可以理解为list下标。

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.tvId.setText(position);
holder.tvState.setText(position+position);
}

5.3返回列表大小

@Override
public int getItemCount() {
return 0;
}

第六步,创建数据接口

创建一个List列表(当然也可以是JsonArray),以此为例,我们创一个Card实体类,为List添加该类泛型。

6.1接下来在CardAdapter创建一个带该list的构造器

List<Card> list;

    public CardAdapter(List<Card> list) {
this.list = list;
}

6.2在getItemCount方法中返回该列表大小

  @Override
public int getItemCount() {
return list == null ? 0 : list.size();
}

6.3在onBindViewHolder方法中绑定真实数据

  @Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.tvId.setText(list.get(position).getId());
holder.tvState.setText(list.get(position).getState());
}

以下为整体代码(文末有我在使用RecycleView中对Adapter的改进代码,如有需要可以参考):

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List; /** @Author: Messi Mei @Date: 2020/8/24 13:46 @Email: 709909986@qq.com */
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.MyViewHolder> {
private List<Card> list; public CardAdapter(List<Card> list) {
this.list = list;
} @NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_rv_card, parent, false);
return new MyViewHolder(view);
} @Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.tvId.setText(list.get(position).getId());
holder.tvState.setText(list.get(position).getState());
} @Override
public int getItemCount() {
return list == null ? 0 : list.size();
} static class MyViewHolder extends RecyclerView.ViewHolder {
private TextView tvId, tvState; MyViewHolder(@NonNull View itemView) {
super(itemView);
tvId = itemView.findViewById(R.id.tv_id);
tvState = itemView.findViewById(R.id.tv_state);
}
}
}

第七步,使用RecycleView

在Activity中创建RecycleView对象并绑定视图,创建Adapter对象。

在initData中初始化数据。

package com.mz.myapplication;

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList;
import java.util.List; public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private CardAdapter cardAdapter;
private List<Card> list; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
} private void initData() {
list = new ArrayList<>();
for (int i = 0; i < 50; i++) {
Card card = new Card();
card.setId(i+1+"");
if (i%2 == 1){
card.setState("在线");
}else{
card.setState("离线");
}
list.add(card);
}
} private void initView() {
recyclerView = findViewById(R.id.rv_card);
cardAdapter = new CardAdapter(list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(cardAdapter);
}
}

至此,运行即可。

如果你想要更复杂的列表布局,在布局文件中加入相应的视图即可,修改完后记得在ViewHolder中加入、绑定相应的视图,在Adapter中的onBindViewHolder为其添加、绑定数据。

而我更推荐以下这种方式,用set方法去设置Adapter中的数据,更加灵活。

package com.mz.myapplication;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList;
import java.util.List; /** @Author: Messi Mei @Date: 2020/8/24 13:46 @Email: 709909986@qq.com */
public class Card2Adapter extends RecyclerView.Adapter<Card2Adapter.MyViewHolder> {
private List<Card> list = new ArrayList<>(); public void setList(List<Card> list) {
this.list = list;
  //一定要记得加
notifyDataSetChanged();
} @NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_rv_card, parent, false);
return new MyViewHolder(view);
} @Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.tvId.setText(list.get(position).getId());
holder.tvState.setText(list.get(position).getState());
} @Override
public int getItemCount() {
return list == null ? 0 : list.size();
} static class MyViewHolder extends RecyclerView.ViewHolder {
private TextView tvId, tvState;
MyViewHolder(@NonNull View itemView) {
super(itemView);
tvId = itemView.findViewById(R.id.tv_id);
tvState = itemView.findViewById(R.id.tv_state);
}
}
}
package com.mz.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import android.os.Bundle; import java.util.ArrayList;
import java.util.List; public class Main2Activity extends AppCompatActivity {
private RecyclerView recyclerView;
private Card2Adapter card2Adapter;
private List<Card> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
initData();
}
private void initData() {
list = new ArrayList<>();
for (int i = 0; i < 50; i++) {
Card card = new Card();
card.setId(i+1+"");
if (i%2 == 1){
card.setState("在线");
}else{
card.setState("离线");
}
list.add(card);
}
card2Adapter.setList(list);
} private void initView() {
recyclerView = findViewById(R.id.rv_card);
card2Adapter = new Card2Adapter();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(card2Adapter);
}
}

这样你可以在任意位置修改列表中的数据。

Android中RecyclerView用法,一步一步教你如何使用RecyclerView以及带你走过编码中可能会出现的坑~的更多相关文章

  1. ZHS16GBK编码中汉字缺失

    生产中使用ZHS16GBK编码的Oracle数据库,若出现字,则会出现乱码 原因是此字不存在在ZHS16GBK编码中 解决方法可以:此二字结构相同,但是后面的在ZHS16GBK编码中出现

  2. 一步一步了解Cocos2dx 3.0 正式版本开发环境搭建(Win32/Android)

    cocos2d-x 3.0发布有一段时间了,作为一个初学者,我一直觉得cocos2d-x很坑.每个比较大的版本变动,都会有不一样的项目创建方式,每次的跨度都挺大…… 但是凭心而论,3.0RC版本开始 ...

  3. 一步一步打造自己的Android图片浏览器(原创)

    今天我们试着来制作一个自己的Android图片浏览器. 图片浏览器应该具有什么功能呢?鉴于不同的人不同的理解,这里提出一个基本的需求: 搜索手机内的所有图片,展示于一个列表中: 列表中展示的是图片的缩 ...

  4. 一步一步学android控件(之十五) —— DegitalClock & AnalogClock

    原本计划DigitalClock和AnalogClock单独各一篇来写,但是想想,两个控件的作用都一样,就和在一起写一篇了. DegitalClock和AnalogClock控件主要用于显示当前时间信 ...

  5. 一步一步学android控件(之十六)—— CheckBox

    根据使用场景不同,有时候使用系统默认的CheckBox样式就可以了,但是有时候就需要自定义CheckBox的样式.今天主要学习如何自定义CheckBox样式.在CheckBox状态改变时有时需要做一些 ...

  6. 一步一步学android控件(之六) —— MultiAutoCompleteTextView

    今天学习的控件是MultiAutoCompleteTextView . 提到MultiAutoCompleteTextView 我们就自然而然地想到AutoCompleteTextView ,就想知道 ...

  7. Ace教你一步一步做Android新闻客户端(一)

    复制粘贴了那么多博文很不好意思没点自己原创的也说不出去,现在写一篇一步一步教你做安卓新闻客户端,借此机会也是让自己把相关的技术再复习一遍,大神莫笑,专门做给新手看. 手里存了两篇,一个包括软件视图 和 ...

  8. android一步一步实现视频clientapp(一)

    我开发完毕了一个完整的视频clientapp.如今.分享出来.供刚開始学习的人学习參考(大神就不用看了,比較简单,仅供入门),大家相互交流相互学习. 项目有些功能,我时间也不是非常多.仅仅能时不时更新 ...

  9. 一步一步教你在 Android 里创建自己的账号系统(一)

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 大家在 ...

随机推荐

  1. Django学习路4_数据库添加元素,读取及显示到网页上

    在 views 中实现对数据库的添加和读取数据库 添加数据 对象 = models 中创建的类名() 对象.列名 = '字段值' 对象.save() 进行保存 return HttpResponse( ...

  2. Kafka和SpringBoot

    事先必备: kafka已安装完成 1.目录结构 2.父pom <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns ...

  3. [C++]类的空指针调用成员函数后,会发生什么事?

    类的实例调用成员函数的原理 其实不管是通过对象实例或指针实例调用,其实底层调用的过程都是一样的,都是把当前对象的指针作为一个参数传递给被调用的成员函数.通过下面的相关实例代码进行检验: 实验的C++代 ...

  4. CF321E Ciel and Gondolas Wqs二分 四边形不等式优化dp 决策单调性

    LINK:CF321E Ciel and Gondolas 很少遇到这么有意思的题目了.虽然很套路.. 容易想到dp \(f_{i,j}\)表示前i段分了j段的最小值 转移需要维护一个\(cost(i ...

  5. java多线程编程实例

    [转]这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下. 1.三个售票窗口同时出售20张票程序分析:   ...

  6. .NetCore 配合 Gitlab CI&CD 实践 - 开篇

    引言 这是一个系列的文章,讲述的是一个中小型开发团队如何从零开始使用搭建基建 GitLab 代码托管平台,以及使用 GitLab Runner 实现 CI/CD 的故事.本系列通过部署一个完整的 .n ...

  7. 仅需1秒!搞定100万行数据:超强Python数据分析利器

    前言 使用Python进行大数据分析变得越来越流行.这一切都要从NumPy开始,它也是今天我们在推文介绍工具背后支持的模块之一. 2 Vaex Vaex是 一种更快.更安全.总体上更方便的方法,可以使 ...

  8. 网络协议: TCP/IP 和UDP/IP

    网络协议: TCP/IP 和UDP/IP TCP/IP TCP/IP(Transmission Control Protocol/Internet Protocol)是一种可靠的网络数据传输控制协议. ...

  9. Docker-Compose介绍,安装和使用

    Docker-Compose 介绍 有时候运行一个镜像需要大量的参数,可以通过Docker-Compose编写这些参数.而且Docker-Compose可以版主我们批量管理容器,这些信息值需要通过一个 ...

  10. FSAF

    Feature Selective Anchor-Free Module for Single-Shot Object Detection https://zhuanlan.zhihu.com/p/5 ...