Android中RecyclerView用法,一步一步教你如何使用RecyclerView以及带你走过编码中可能会出现的坑~

首先,要明白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。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/rv_card"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

第三步,为RecyclerView中的item创建一个统一的布局文件

在layout下创建一个名为layout_rv_card的布局文件,文件名命名要和你的实际业务相匹配方便后期查找。

 在此布局文件中,可以添加任何你想展示的视图,在这里我们先创建两个TextView为大家展示:

<?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="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" />
</LinearLayout>

  别忘了添加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: 709909986@qq.com
 **/
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: 709909986@qq.com
 **/
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.MyViewHolder> {

    @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的构造器

List<Card> list;

    public CardAdapter(List<Card> 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: 709909986@qq.com */
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.MyViewHolder> {
  private List<Card> list;

  public CardAdapter(List<Card> 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 List<Card> list;

  @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: 709909986@qq.com */
public class Card2Adapter extends RecyclerView.Adapter<Card2Adapter.MyViewHolder> {
  private List<Card> list = new ArrayList<>();

  public void setList(List<Card> 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 List<Card> list;
    @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);
    }
}

这样你可以在任意位置修改列表中的数据。

原文地址:https://www.cnblogs.com/mzxiaoze/p/13554222.html