RecyclerView系列 - RecyclerView的基本使用

文章欢迎转载,转载请注明出处:文章首发于【Karen Chia の 程序人生】RecyclerView系列 - RecyclerView的基本使用

按照惯例,先上效果图

在这里插入图片描述
效果图不是我想要的效果,怎么办?

查看关于 RecyclerView 系列的其它文章,总有你想要的效果 ↓↓↓

KarenChia 的 RecyclerView 系列文章

RecyclerView系列 - RecyclerView的基本使用

RecyclerView系列 - 如何优雅的实现分割线

前言

RecyclerView 在本文发布之前,已经出来很久了,之前也有很多关于 RecyclerView 的优秀文章,那我为什么还要在这里写下本文呢,实不相瞒,我是 ListView 的忠实粉,之前很少使用到 RecyclerView,最近发现了不少关于 RecyclerView 的优秀框架,于是开始使用 RecyclerView,在使用第三方优秀框架的同时,也需要了解框架背后对组件进行的处理及封装,便于后期对项目维护。

为什么选择 RecyclerView?

相对于 ListView、GridView 这类滑动列表组件来说,RecyclerView 具有:

  • 使用更加灵活
    1 通过设置布局管理器,可轻松实现组件列表垂直滑动或水平滑动效果
    2 给列表的 item 项设置【增加或删除】动画
    3 当列表组件滑动到顶端或底部时,带有波纹效果,更显列表立体感
  • 代码高度解耦
    代码高幅度降低了耦合度,维护起来非常方便
  • 拓展方便
    1 轻松实现 ListView 及 Gridview 组件的相关列表效果,学会 RecyclerView,相当于学会了 ListView + Gridview
    2 难得一见的【瀑布流】列表滑动效果

RecyclerView 不是万能的,存在以下不足:

  • 不像 ListView那样,它没有分割线的设置方法
  • 没有实现 item 的相关点击事件

但是,重点来了:

也正是由于 RecyclerView 存在的这些缺点,我们不就可以根据自己的需求去定义嘛,怎么开心怎么玩!!!

下面开始进入我们今天的主题 ↓↓↓

1 添加依赖

在 module(一般都是在 app 下) 的 build.gradle 文件下添加组件依赖:

implementation 'androidx.recyclerview:recyclerview:1.0.0'

注意:由于使用的 Android Studio 版本不同,依赖语句也有所不同,我这里使用的 AS 版本是 V3.4.1

2 在布局文件中使用 RecyclerView

<?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="match_parent"
    android:background="@color/app_bg"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvTest"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

3 为 RecycleView 设置布局管理器 LinearLayoutManager

这里列表默认是垂直滑动的

rvTest.setLayoutManager(new LinearLayoutManager(this));

不要问我为什么,问就【看源码】,看 LinearLayoutManager 构造器源码:

    /**
     * Creates a vertical LinearLayoutManager
     *
     * @param context Current context, will be used to access resources.
     */
    public LinearLayoutManager(Context context) {
        this(context, RecyclerView.DEFAULT_ORIENTATION, false);
    }

关于 DEFAULT_ORIENTATION 的定义如下:

static final int DEFAULT_ORIENTATION = VERTICAL;

关于 VERTICAL 的定义如下:

public static final int VERTICAL = LinearLayout.VERTICAL;

源码中使用的属性还是线性布局 LinearLayout 的垂直属性

那么问题来了,我要让 RecyclerView 水平滑动怎么办?

3.1 设置 RecyclerView 列表水平滑动

        LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
        mLinearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        rvTest.setLayoutManager(mLinearLayoutManager);

4 设置 item 增加和删除时的动画效果

rvTest.setItemAnimator(new DefaultItemAnimator());

这里设置的是 RecyclerView 默认的动画效果

5 设置适配器

        mRecyclerViewTestAdapter = new RecyclerViewTestAdapter(this, testData);
        rvTest.setAdapter(mRecyclerViewTestAdapter);

RecyclerView 的适配器继承至 RecyclerView.Adapter < VH extends ViewHolder >,泛型类型为ViewHolder。

RecyclerView 对 ViewHolder 进行了封装,使得我们使用起来更加的方便,自定义的 ViewHolder 只需继承 RecyclerView.ViewHolder 即可

package com.karenchia.andprimarylp.adapter;

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 com.karenchia.andprimarylp.R;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * RecyclerView 测试数据适配器
 * <p>
 * Created by KarenChia on 2019/9/4.
 */
public class RecyclerViewTestAdapter extends RecyclerView.Adapter<RecyclerViewTestAdapter.RecyclerViewTestViewHolder> {
    /**
     * 上下文对象
     */
    private Context mContext;
    /**
     * 测试数据
     */
    private List<String> testDataList;

    /**
     * 函数构造器
     *
     * @param mContext     上下文对象
     * @param testDataList 测试数据
     */
    public RecyclerViewTestAdapter(Context mContext, List<String> testDataList) {
        this.mContext = mContext;
        this.testDataList = testDataList;
    }

    /**
     * 加载 item 的布局文件
     */
    @NonNull
    @Override
    public RecyclerViewTestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new RecyclerViewTestViewHolder(
                LayoutInflater.from(mContext).inflate(R.layout.item_recycler_view_test, parent, false));
    }

    /**
     * 将数据与 item 视图进行绑定
     */
    @Override
    public void onBindViewHolder(@NonNull RecyclerViewTestViewHolder holder, int position) {
        holder.tvData.setText(testDataList.get(position));
    }

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

    /**
     * RecycleView 中 ViewHolder 的定义方式
     */
    public class RecyclerViewTestViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.tvData)
        TextView tvData;

        public RecyclerViewTestViewHolder(@NonNull View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
}

列表 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:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:id="@+id/tvData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black" />
</LinearLayout>

至此,RecyclerView 的基本用法结束。

6 相关类的代码

这里贴一下相关类的代码实现

项目使用的是 MVP 模式,别问我为什么要使用 MVP 模式,问就请看这里:https://blog.csdn.net/ZhaiKun68/article/details/100033584#1_AndroidMVP_3

6.1 RecyclerViewDemoContract 类

package com.karenchia.andprimarylp.ui.contract;

import java.util.List;

/**
 * MVP 模式接口抽取
 * <p>
 * Created by KarenChia on 2019/9/4.
 */
public interface RecyclerViewDemoContract {

    interface Model {
        /**
         * 加载测试数据
         *
         * @return 测试数据
         */
        List<String> testData();
    }

    interface View {
        /**
         * 显示测试数据列表
         *
         * @param testData 测试数据
         */
        void showTestData(List<String> testData);
    }

    interface Presenter {
        /**
         * 获取测试数据
         */
        void getTestData();
    }
}

6.2 RecyclerViewDemoModel 类

package com.karenchia.andprimarylp.ui.model;

import com.karenchia.andprimarylp.ui.contract.RecyclerViewDemoContract;

import java.util.ArrayList;
import java.util.List;

/**
 * model 层数据逻辑处理
 * <p>
 * Created by KarenChia on 2019/9/4.
 */
public class RecyclerViewDemoModel implements RecyclerViewDemoContract.Model {

    /**
     * 加载测试数据
     *
     * @return 测试数据
     */
    @Override
    public List<String> testData() {
        List<String> testData = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            testData.add("我是 Karen Chia " + i);
        }
        return testData;
    }
}

6.3 RecyclerViewDemoActivity 类

package com.karenchia.andprimarylp.ui.activity.newfeature;

import android.content.Context;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.karenchia.andprimarylp.R;
import com.karenchia.andprimarylp.adapter.RecyclerViewTestAdapter;
import com.karenchia.andprimarylp.ui.contract.RecyclerViewDemoContract;
import com.karenchia.andprimarylp.ui.presenter.RecyclerViewDemoPresenter;
import com.socks.library.KLog;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * RecyclerView 演示类 view 层逻辑处理
 * <p>
 * Created by KarenChia on 2019/9/3.
 */
public class RecyclerViewDemoActivity extends AppCompatActivity implements RecyclerViewDemoContract.View {
    /**
     * view层与model层交互的桥梁
     */
    private RecyclerViewDemoContract.Presenter mPresenter;

    /**
     * RecyclerView 组件
     */
    @BindView(R.id.rvTest)
    RecyclerView rvTest;

    /**
     * RecyclerView 的数据适配器
     */
    private RecyclerViewTestAdapter mRecyclerViewTestAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view_demo);
        ButterKnife.bind(this);
        mPresenter = new RecyclerViewDemoPresenter(this);
        initData();
        initView();
    }

    private void initData() {
        mPresenter.getTestData();
    }

    /**
     * 组件初始化
     */
    private void initView() {
        //为 RecycleView 设置布局管理器
        rvTest.setLayoutManager(new LinearLayoutManager(this));
        //LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
        //mLinearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        //rvTest.setLayoutManager(mLinearLayoutManager);
        //设置 item 增加和删除时的动画效果
        rvTest.setItemAnimator(new DefaultItemAnimator());
    }

    /**
     * 显示测试数据列表
     *
     * @param testData 测试数据
     */
    @Override
    public void showTestData(List<String> testData) {
        //设置适配器
        mRecyclerViewTestAdapter = new RecyclerViewTestAdapter(this, testData);
        rvTest.setAdapter(mRecyclerViewTestAdapter);
    }
}

6.4 RecyclerViewDemoPresenter 类

package com.karenchia.andprimarylp.ui.presenter;

import com.karenchia.andprimarylp.ui.contract.RecyclerViewDemoContract;
import com.karenchia.andprimarylp.ui.model.RecyclerViewDemoModel;

/**
 * model层 与 View层 通信的桥梁
 * <p>
 * Created by KarenChia on 2019/9/4.
 */
public class RecyclerViewDemoPresenter implements RecyclerViewDemoContract.Presenter {
    /**
     * model层数据逻辑处理
     */
    private RecyclerViewDemoContract.Model mModel;
    /**
     * view层交互逻辑处理
     */
    private RecyclerViewDemoContract.View mView;

    public RecyclerViewDemoPresenter(RecyclerViewDemoContract.View mView) {
        mModel = new RecyclerViewDemoModel();
        this.mView = mView;
    }

    /**
     * 获取测试数据
     */
    @Override
    public void getTestData() {
        mView.showTestData(mModel.testData());
    }
}

看官,如果喜欢我的文章,请点个【关注】呗,方便看官下次查看哟!!!

发布了101 篇原创文章 · 获赞 52 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/ZhaiKun68/article/details/100557688