首先,要明白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。
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"/>
第三步,为RecyclerView中的item创建一个统一的布局文件
在layout下创建一个名为layout_rv_card的布局文件,文件名命名要和你的实际业务相匹配方便后期查找。
在此布局文件中,可以添加任何你想展示的视图,在这里我们先创建两个TextView为大家展示:
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" />
别忘了添加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: [email protected] **/ 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: [email protected] **/ public class CardAdapter extends RecyclerView.Adapter{ @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的构造器
Listlist; public CardAdapter(List 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: [email protected] */ public class CardAdapter extends RecyclerView.Adapter{ private List list; public CardAdapter(List 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 Listlist; @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: [email protected] */ public class Card2Adapter extends RecyclerView.Adapter{ private List list = new ArrayList<>(); public void setList(List 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 Listlist; @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); } }
这样你可以在任意位置修改列表中的数据。