本文是博主对Adapter(适配器)的一些理解,为了加深对Adapter的理解以及记录自己的阶段学习而写,同时也适合初学者阅读,参考本条博客的逻辑进行学习。
首先需要的代码如下:
目录
(1)XML主代码
首先布置主界面的布局,就一个recyclerview即可
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler" />
</LinearLayout>
(2)XML布局文件
接下来设置recyclerview中每个item的布局
<?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="wrap_content"
android:background="#FFFFFF"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:paddingRight="20dp"
android:paddingLeft="20dp">
<ImageView
android:id="@+id/imagess"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"
android:src="@android:mipmap/sym_def_app_icon" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/news"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="#666666" />
</LinearLayout>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="end"
android:textColor="#999999"
android:textSize="14sp"
android:text="2021年4月24日\n19:02:50"/>
</LinearLayout>
(3)Java内容类Message
接着就是设置每个item的内容是什么类型的,把所有内容聚集成一个对象,方便后续从对象中获取需要的内容
package com.example.recyclerview;
public class Message {
private int imageId;
private String name;
private String subText;
private String time;
public int getImageId() {
return imageId;
}
public String getName() {
return name;
}
public String getTime() {
return time;
}
public String getSubText() {
return subText;
}
public Message(int imageId, String name, String subText,String time) {
this.imageId = imageId;
this.name = name;
this.subText = subText;
this.time=time;
}
}
(4)Java主代码
接下来初始化控件,初始化数据,给控件设置布局,最后绑定适配器。
public class MainActivity extends AppCompatActivity{
RecyclerView recyclerView;
List<Message> list = new ArrayList<Message>();
LinearLayoutManager linearLayoutManager;
recy_Adapter recy_adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initview();
initdata();
settinglayout();
binddata();
}
//给recycler设置一个布局
private void settinglayout() {
linearLayoutManager = new LinearLayoutManager
(this, RecyclerView.VERTICAL, false);
}
//为控件绑定适配器
private void binddata() {
recy_adapter = new recy_Adapter(this, list);
recyclerView.setAdapter(recy_adapter);
recyclerView.setLayoutManager(linearLayoutManager);
}
//初始化List的数据
private void initdata() {
Message message1 = new Message(R.drawable.like, "喜欢"
, "想要去北极玩", "2021年4月24日"+"\n"+"19:06:50");
list.add(message1);
Message message2 = new Message(R.drawable.local, "定位"
, "想要去北极", "2021年4月24日"+"\n"+"19:06:50");
list.add(message2);
Message message3 = new Message(R.drawable.report, "举报"
, "想要去北", "2021年4月24日"+"\n"+"19:06:50");
list.add(message3);
Message message4 = new Message(R.drawable.share, "分享"
, "想要去", "2021年4月24日"+"\n"+"19:06:50");
list.add(message4);
}
//找控件
private void initview() {
recyclerView = findViewById(R.id.recycler);
}
(5)Java适配器recy_Adapter类
最后是自定义适配器一开始实现接口会爆红,把接口实现了就正常,就是以下这个图。
public class recy_Adapter extends RecyclerView.Adapter<recy_Adapter.MyAdapter> {
@NonNull
@Override
public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
public class MyAdapter extends RecyclerView.ViewHolder{
public MyAdapter(@NonNull View itemView) {
super(itemView);
}
}
}
然后写入传统方法,已注释
/*
① 创建一个继承RecyclerView.Adapter<VH>的Adapter类
② 创建一个继承RecyclerView.ViewHolder的静态内部类
③ 在Adapter中实现3个方法:
onCreateViewHolder()
onBindViewHolder()
getItemCount()
*/
public class recy_Adapter extends RecyclerView.Adapter<recy_Adapter.MyAdapter>{
Context context;
List<Message> list=new ArrayList<Message>();
//构造方法
public recy_Adapter(Context context, List<Message> list) {
this.context = context;
this.list = list;
}
@Override
//返回Item总条数
public int getItemCount() {
return list == null ? 0 : list.size();
}
@NonNull
@Override
//创建ViewHolder,返回每一项的布局
public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//用LayoutInflater类的方法创建一个layoutinflater对象
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//调用inflater方法实例化recy_list的xml文件,并返回View对象还赋予一个parent父布局
View view = layoutInflater.inflate(R.layout.recy_list, parent, false);
//把布局中的控件利用自己创建的类给绑定起来,此时myAdapter就有了某个item里面的所有控件
MyAdapter myAdapter = new MyAdapter(view);
//返回对象
return myAdapter;
}
@Override
//将数据和控件绑定,获取List中对应的数据然后set到控件中(简单来说就是设置item中的控件信息)
//第一个参数是onCreateViewHolder回调中的返回值,等于你那项item和里面的控件都获取了
//第二个参数是每个item在List数据中的位置,从0开始数
public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
//获取List列表中对应位置的Message的对象
Message message = list.get(position);
//从对象中取出对应的字段数据
holder.image.setImageResource(message.getImageId());
holder.name.setText(message.getName());
holder.subtext.setText(message.getSubText());
holder.time.setText(message.getTime());
}
//内部类,绑定控件
public class MyAdapter extends RecyclerView.ViewHolder{
//布局有什么控件就写定义什么
TextView name,subtext,time;
ImageView image;
//找item里的控件
public MyAdapter(@NonNull View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imagess);
name = itemView.findViewById(R.id.name);
subtext = itemView.findViewById(R.id.news);
time = itemView.findViewById(R.id.time);
}
}
用ViewBinding优化后的Adapter
public class recy_Adapter extends RecyclerView.Adapter<recy_Adapter .MyAdapter> {
private final Context context;
private final List<Message> list;
public recy_Adapter (Context context, List<Message> list) {
this.context= context;
this.list= list;
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size();
}
@NonNull
@Override
public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemListBinding it=ItemListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false))
return new MyAdapter(it);
}
@Override
public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
Message message = list.get(position);
holder.mView.image.setImageResource(message .getImageId());
holder.mView.name.setText(message .getName());
holder.mView.subtext.setText(message .getSubText());
holder.mView.time.setText(message .getTime());
}
static class MyAdapter extends RecyclerView.ViewHolder {
ItemListBinding mView;
public MyAdapter (ItemListBinding itemView) {
super(itemView.getRoot());
this.mView = itemView;
}
}
}
通俗的说,inflate就相当于将一个xml中定义的布局找出来。
因为在一个Activity里如果直接用findViewById()的话,找的是setConentView()的那个layout布局里的组件。
因此如果你的Activity里如果用到别的layout,比如对话框上的layout布局,你还要设置对话框上的layout布局里的组件像ImageView,TextView上的内容,你就必须用inflate()先将对话框上的layout布局找出来,然后再用这个layout布局对象去找到它上面的组件,如:
从一个Context中,获得一个布局填充器,这样你就可以使用这个填充器来把xml布局文件转为View对象了。
//加载整个应用的布局管理器
LayoutInflater layoutInflater= LayoutInflater.from(context);
//利用布局管理器,将xml布局转换为view对象
convertView = layoutInflater.inflate(R.layout.item_myseallist,parent, false);
//利用view对象,找到xml布局中的组件
convertView.findViewById(R.id.delete);
(6)效果图
上面已经注释的挺简单了,后面我觉得不好再修改,下面就是写完后的效果,但是还没有设置点击事件,后面我写完的时候再更新一下博客。