本文是博主对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)效果图
上面已经注释的挺简单了,后面我觉得不好再修改,下面就是写完后的效果,但是还没有设置点击事件,后面我写完的时候再更新一下博客。