目录
第三步:再添加一个news_item_layout.xml的布局文件,用于显示一条数据编辑
概述
RecyclerView是Android中非常受欢迎的控件,RecyclerView是官方在Android5.0之后新添加的控件,推出用来替代传统的ListView和GridView列表控件,所以如果你还在使用ListView的话可以替换为RecyclerView了。
对于RecyclerView的使用根据实际项目进行说明,一些功能可能是你现在正在做的,对你有帮助也说不定。
一、RecyclerView基础使用
第一步:在build.gradle
中添加依赖
implementation ("androidx.recyclerview:recyclerview:1.1.0")//可横向滚动
第二步:添加RecyclerView
点开一个布局文件,找到RecyclerView
控件,拖动到要添加的位置即可添加RecyclerView
。
xml代码如下:
<?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.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="1dp"
android:background="#6750A4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="实例"
android:textColor="#FFFFFF"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="409dp"
android:layout_height="688dp"
android:layout_marginTop="1dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/constraintLayout">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleview"
android:layout_width="409dp"
android:layout_height="688dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
第三步:再添加一个news_item_layout.xml
的布局文件,用于显示一条数据
在根布局上面设置好每条显示的数据的长宽,并添加内容到根布局里面。
代码如下:
<?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="90dp">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="title"
android:textColor="#000000"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="5dp"
android:text="content"
android:textColor="#707070"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
第四步:添加逻辑代码
定义一个实体类:
实体类代码如下:
public class News {
public String title; // 标题
public String content; //内容
}
然后在MainActivity中定义内部类 ViewHolder
类、 MyAdapter
类以及设置RecyclerView
相关逻辑
首先是内部类 MyViewHolder
类:用于初始化控件
class MyViewHoder extends RecyclerView.ViewHolder {
TextView title;
TextView content;
public MyViewHoder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.textView2);
content = itemView.findViewById(R.id.textView3);
}
}
再就是内部类 MyAdapter
类:将添加到的数据与item进行绑定
class MyAdapter extends RecyclerView.Adapter<MyViewHoder> {
//绑定item布局
@NonNull
@Override
public MyViewHoder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = View.inflate(MainActivity.this, R.layout.news_item_layout, null);
MyViewHoder myViewHoder = new MyViewHoder(view);
return myViewHoder;
}
//给item添加数据
@Override
public void onBindViewHolder(@NonNull MyViewHoder holder, int position) {
News news = newsList.get(position);
holder.title.setText(news.title);
holder.content.setText(news.content);
}
//设置item条数
@Override
public int getItemCount() {
return newsList.size();
}
}
最后就是构造数据:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.recycleview);
// 构造一些数据
for (int i = 0; i < 100; i++) {
News news = new News();
news.title = "标题" + i;
news.content = "内容" + i;
newsList.add(news);
}
mMyAdapter = new MyAdapter();
mRecyclerView.setAdapter(mMyAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setLayoutManager(layoutManager);
}
完整 MainActivity.java 代码:
package com.example.retrofit;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
MyAdapter mMyAdapter ;
List<News> newsList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.recycleview);
// 构造一些数据
for (int i = 0; i < 50; i++) {
News news = new News();
news.title = "标题" + i;
news.content = "内容" + i;
newsList.add(news);
}
mMyAdapter = new MyAdapter();
mRecyclerView.setAdapter(mMyAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setLayoutManager(layoutManager);
}
class MyAdapter extends RecyclerView.Adapter<MyViewHoder> {
//绑定item布局
@NonNull
@Override
public MyViewHoder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = View.inflate(MainActivity.this, R.layout.news_item_layout, null);
MyViewHoder myViewHoder = new MyViewHoder(view);
return myViewHoder;
}
//给item添加数据
@Override
public void onBindViewHolder(@NonNull MyViewHoder holder, int position) {
News news = newsList.get(position);
holder.title.setText(news.title);
holder.content.setText(news.content);
}
//设置item条数
@Override
public int getItemCount() {
return newsList.size();
}
}
class MyViewHoder extends RecyclerView.ViewHolder {
TextView title;
TextView content;
public MyViewHoder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.textView2);
content = itemView.findViewById(R.id.textView3);
}
}
}
若要实现横向滑动:在 MainActivity.java 添加一句如下代码
layoutManager.setOrientation(RecyclerView.HORIZONTAL);
若要每行显示多条数据,可对代码做如下修改:
mRecyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this,3));//每行三个
运行效果如下:
二、RecyclerView进阶使用:通过网络请求得到数据
前期准备:添加依赖包:
implementation("com.squareup.okhttp3:okhttp:4.11.0")
implementation ("com.squareup.retrofit2:retrofit:2.9.0")
implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
implementation ("io.github.youth5201314:banner:2.2.3")
implementation ("com.github.bumptech.glide:glide:4.15.1")
implementation ("com.google.code.gson:gson:2.10.1")
添加网络请求权限:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
android:allowBackup="true"
添加一些数据到mock中去(useMock 免费在线Mock平台 Api数据模拟助手)
重新构造实体类:
获取网络数据,将网络数据赋值给newsDTOList数组
// 构造一些数据
Request request = new Request.Builder()
.url("https://detail.usemock.com/shiyan")
.get().build();
OkHttpClient okHttpClient = new OkHttpClient();
Call call = okHttpClient.newCall(request);
//构造item数据
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
String result = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
Gson gson = new Gson();
News news = gson.fromJson(result,News.class);
newsDTOList.addAll(news.news);
mMyAdapter.notifyDataSetChanged();
}catch (Exception e){
throw new RuntimeException(e);
}
}
});
}
});
再对MainActivity中定义内部类 ViewHolder
类、 MyAdapter
类以及设置RecyclerView
相关逻辑的修改。具体操作很简单,这里省略,下面是完整的代码,供参考:
MainActivity.java代码:
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
MyAdapter mMyAdapter ;
List<News.NewsDTO> newsDTOList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.recycleview);
DividerItemDecoration mDivider = new
DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(mDivider);
// 构造一些数据
Request request = new Request.Builder()
.url("https://detail.usemock.com/shiyan")
.get().build();
OkHttpClient okHttpClient = new OkHttpClient();
Call call = okHttpClient.newCall(request);
//构造item数据
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
String result = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
Gson gson = new Gson();
News news = gson.fromJson(result,News.class);
newsDTOList.addAll(news.news);
mMyAdapter.notifyDataSetChanged();
}catch (Exception e){
throw new RuntimeException(e);
}
}
});
}
});
mMyAdapter = new MyAdapter();
mRecyclerView.setAdapter(mMyAdapter);
//mRecyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this,3));//每行三个
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
//layoutManager.setOrientation(RecyclerView.HORIZONTAL);
mRecyclerView.setLayoutManager(layoutManager);
}
class MyAdapter extends RecyclerView.Adapter<MyViewHoder> {
//绑定item布局
@NonNull
@Override
public MyViewHoder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = View.inflate(MainActivity.this, R.layout.news_item_layout, null);
MyViewHoder myViewHoder = new MyViewHoder(view);
return myViewHoder;
}
//给item添加数据
@Override
public void onBindViewHolder(@NonNull MyViewHoder holder, int position) {
News.NewsDTO newsDTO = newsDTOList.get(position);
holder.title.setText(newsDTO.title);
Glide.with(MainActivity.this).load(newsDTO.content).into(holder.content);
}
//设置item条数
@Override
public int getItemCount() {
return newsDTOList.size();
}
}
class MyViewHoder extends RecyclerView.ViewHolder {
TextView title;
ImageView content;
public MyViewHoder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.textView2);
content = itemView.findViewById(R.id.imageView);
}
}
}
activity_main.xml代码:
<?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.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="1dp"
android:background="#6750A4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="实例"
android:textColor="#FFFFFF"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="409dp"
android:layout_height="688dp"
android:layout_marginTop="1dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/constraintLayout">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleview"
android:layout_width="409dp"
android:layout_height="688dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
News.java代码:
import java.util.List;
public class News {
@com.google.gson.annotations.SerializedName("news")
public List<NewsDTO> news;
public static class NewsDTO {
@com.google.gson.annotations.SerializedName("title")
public String title;
@com.google.gson.annotations.SerializedName("content")
public String content;
}
}
news_item_layout.xml代码:
<?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="200dp"
android:layout_height="150dp">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="title"
android:textColor="#000000"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2"
app:srcCompat="@drawable/ic_launcher_background" />
</androidx.constraintlayout.widget.ConstraintLayout>
运行效果: