ps:拖延症晚期...拖到现在才写,我是废物
OK,废话不多说,继续我们的实验,上次做完整体界面的布局后,这次开始对界面实现RecyclerView。(就类似于微信界面的滚动)
一:什么是RecyclerView
官方解释如下:
A flexible view for providing a limited window into a large data set.
意思就是说在一个有限的窗口中显示大量的数据集。
回顾一下以前我们使用的ListView ListView的局限
-
只有纵向列表一种布局
-
没有支持动画的API
-
接口设计和系统不一致 setOnItemClickListener() setOnItemLongClickListener() setSelection()
-
没有强制实现ViewHolder
-
性能不如RecyclerView
下面我们看看RecyclerView的几个重要组件:
二:RecyclerView的基本使用
在使用RecyclerView时候,必须指定一个适配器Adapter和一个布局管理器LayoutManager。
我们这样思考,当我们去完成一个界面的布局时,我们要向里面传数据,怎么去传呢?全写在xml文件里显而不合适,这就是Adapter的作用。
简而言之,Adapter就是数据与ui之间的桥梁,它把数据与前端ui连接到一起,是一个展示数据的载体。
而设置布局管理器RecyclerView则是来控制Item的布局方式,横向、竖向以及瀑布流方式
例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的还StaggeredGridLayoutManager等)。也就是说RecyclerView不再拘泥于ListView的线性展示方式,它也可以实现GridView的效果等多种效果。
下面我们展示RecyclerView的基本使用方法:
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this );
//设置布局管理器
recyclerView.setLayoutManager(layoutManager);
//设置为垂直布局,这也是默认的
layoutManager.setOrientation(OrientationHelper. VERTICAL);
//设置Adapter
recyclerView.setAdapter(recycleAdapter);
//设置分隔线
recyclerView.addItemDecoration( new DividerGridItemDecoration(this ));
//设置增加或删除条目的动画
recyclerView.setItemAnimator( new DefaultItemAnimator());
现在我们了解了什么是RecyclerView,RecyclerView的作用是什么,RecyclerView的基本使用,下面,我们正式开始对上次的实验进行完善。
三:修改原有xml文件
为了实现RecyclerView,我们将初始的xml文件修改为ConstrainLayout(约束布局)并添加RecyclerView。 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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/tab02_RecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:layout_margin="8dp"
android:overScrollMode="never"
android:scrollbars="none" />
现在,我们已经有了一个RecycleView的视图,接下来,我们要向里面添加东西。
四:创建RecyclerView的item.xml
当我们创建好RecyclerView时,我们思考,我们现在拥有的不管是一片空白。
我们把RecycleView视为一个大的集装箱,现在大的集装箱需要向里面添加一个个模式固定的小盒子,而小盒子里存放的就是我们的数据。
那么我们现在需要做的就是创建这个小盒子的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:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="8dp"
android:background="@android:color/darker_gray"
android:orientation="vertical">
<TextView
android:id="@+id/item02_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
tools:text="1" />
<TextView
android:id="@+id/item02_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
tools:text="内容" />
</LinearLayout>
RecyclerView与item的xml代码其实都不难理解,真正的重点在我们接下来要讲的东西。
五:修改Fragment文件
在上一步,我们已经造好了存放数据的“小盒子”。但是盒子里什么都没有啊,没有数据啊。
这时候就需要修改之前的Fragment文件,在Fragment里创建List,然后再调用Adapter将List里的数据传入到“小盒子”。
(*注意!不是MainActivity*)
MainActivity只是起的更多的是一个整体的调动作用(也就是页面的切换)
而每个界面自己的控制,数据输入等则是它自己的Fragment。
老样子,首先在Fragment里进行声明:
// 添加存储数据的列表
private List<String> mList = new ArrayList<>();
private Context context;
private RecyclerView recyclerView;
private VerticalAdapter verticalAdapter;
然后修改onCrete函数,onCreate函数起到的作用可以看作是对界面的初始化。
在这里,我们对view、context、adapter、LinearLayoutManager以及list赋值。
代码如下:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.tab02, container, false);
context = view.getContext();
recyclerView = view.findViewById(R.id.tab02_RecyclerView);
initData();
LinearLayoutManager manager = new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.VERTICAL);
verticalAdapter = new VerticalAdapter(mList,context);
recyclerView.setAdapter(verticalAdapter);
recyclerView.setLayoutManager(manager);
return view;
}
private void initData() {
//向list里添加数据
mList.add("亚特兰大老鹰");
mList.add("夏洛特黄蜂");
mList.add("迈阿密热火");
mList.add("奥兰多魔术");
mList.add("华盛顿奇才");
mList.add("波士顿凯尔特人");
mList.add("布鲁克林篮网");
mList.add("纽约尼克斯");
mList.add("费城76人");
mList.add("多伦多猛龙");
mList.add("芝加哥公牛");
mList.add("克里夫兰骑士");
mList.add("底特律活塞");
}
因为我们的Adapter是需要自己创建的,因此,我们新建一个java类,继承RecyclerView.Adapter。
六:创建自定义Adapter
在这里,我们通过构造函数对list与context赋值。
然后,重载函数:
-
onCreateViewHolder(ViewGroup parent, int viewType) 方法。
这个方法用于加载 RecyclerView 子项的布局,然后返回一个 ViewHolder 对象,ViewHolder 是一个静态内部类,继承自 RecyclerView.ViewHolder 类。
-
onBindViewHolder(ViewHolder viewHolder, int i) 方法。
上面那个方法为子项加载布局,这个方法为子项绑定数据。调用这两个方法后,子项就既有了布局又有了数据。
-
getItemCount() 方法。
用于获取 RecyclerView 一共有多少子项。
在这里,补充一个知识点,关于RecyclerView的调用顺序总是按照:
获取大小——>绑定布局——>加载ViewHolder类——>绑定数据
这样一个规律的,通过这样的规律,我们就能知道是按照怎样的顺序来调用这些重载函数的了。
代码如下:
package com.example.likewechat;
import android.content.Context;
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;
public class VerticalAdapter extends RecyclerView.Adapter<VerticalAdapter.VerticalViewHolder> {
private Context mContext;
private List<String> mList;
public VerticalAdapter(List<String> list, Context context) {
mList = list;
mContext = context;
}
@NonNull
@Override
public VerticalAdapter.VerticalViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(this.mContext).inflate(R.layout.item02, parent, false);
return new VerticalViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull VerticalViewHolder holder, int position) {
holder.tvNum.setText(position + 1 + "");
holder.tvContent.setText(mList.get(position));
}
@Override
public int getItemCount() {
return mList == null ? 0 : mList.size();
}
public static class VerticalViewHolder extends RecyclerView.ViewHolder {
TextView tvNum, tvContent;
public VerticalViewHolder(View itemView) {
super(itemView);
tvNum = itemView.findViewById(R.id.item02_num);
tvContent = itemView.findViewById(R.id.item02_content);
}
}
}
七:结果展示
八:关于Adapter的总结
每当 RecyclerView 的子项出现在屏幕上时或将要出现在屏幕上时,系统会按照如下的顺序调用函数。
-
调用 getItemCount() 方法获取子项的数量。
-
调用 onCreateViewHolder(ViewGroup parent, int viewType) 方法加载每一个子项的布局
-
构造一个 ViewHolder 对象。
-
调用 onBindViewHolder(ViewHolder viewHolder, int i) 方法将数据绑定在 ViewHolder 对象中。
探究 RecyclerView 适配器重载函数的调用顺序就完成了,还要提醒一下的就是,当所有子项加载完后,移出屏幕的子项再次回到屏幕中时,是不会再次构造 ViewHolder 对象的,也就是说这个对象已经被构造过了,再次出现在屏幕中只需要复用就可以了。
参考博客: 探究RecyclerView适配器中重载函数的作用以及调用顺序
Gitee源码:gitee.com/White-9/Lik…