如何在 Android RecyclerView 中使用 Volley 实现分页?


分页在处理大量数据的应用程序中起着至关重要的作用,它可以提高性能和用户体验。希望在 RecyclerView 和 Volley 中实现分页的 Android 开发人员必须考虑几个重要因素。

开发人员可以通过使用 RecyclerView 和 Volley 来实现无缝的分页体验。这两个强大的工具可以处理大型列表和多功能的网络功能。使用这种方法,数据可以分批加载,从而减少内存消耗,并实现更流畅的内容滚动。

开发人员可以通过使用分页来获得更好的性能并在 Android 设备上提供出色的用户体验。此技术提高了用户的响应速度和浏览效率。

Android RecyclerView

Android RecyclerView 是一个用于以组织且无缝的方式显示大型数据集的有用工具。它就像一个容器,可以显示多个视图作为列表项,称为“ViewHolder”。此 RecyclerView 是 ListView 的现代化、更高级的版本,具有可定制的功能,供开发人员增强其功能和视觉吸引力。

与 ListView 相比,RecyclerView 采用了不同的方法。它将布局和动画职责委托给专门的类,利用“LayoutManager”以网格、线性或交错的方式排列项目。此外,它还配备了用户交互功能,可以开箱即用地处理项目点击事件和长按手势。

RecyclerView 中的“Adapter”类有助于高效地更新数据。通过创建自定义适配器将数据与视图关联,开发人员可以实现动态修改和流畅滚动。从本质上讲,Android RecyclerView 提供了一种有效且引人注目的方法来展示移动应用程序中的信息列表和网格。

方法

要使用 Volley 库在 Android RecyclerView 中进行分页,请按照以下概述的步骤操作。由于分页有多种方法,因此这里将讨论两种常用方法

  • 无限滚动

  • “加载更多”按钮

无限滚动

为了在 RecyclerView 中实现无缝滚动和持续加载数据,将滚动监听器附加到它。当用户到达列表末尾时,应用程序将最后一个可见项与总数进行比较,以检查是否已加载所有数据。如果否,Volley 会从服务器获取更多信息,这些信息会添加到现有数据中,然后通知适配器中的更改。当浏览内容丰富的长列表时,此方法使用户导航更加轻松。

算法

  • 设置您的 RecyclerView 和 Adapter:创建 RecyclerView 实例并设置您的自定义适配器以将数据绑定到视图。

  • 实现滚动监听器:使用 addOnScrollListener() 将滚动监听器附加到 RecyclerView。此监听器将检测用户何时到达列表末尾。

  • 检测列表末尾:在滚动监听器的 onScrolled() 方法中,检查最后一个可见项是否已到达总项目数。如果是,则表示用户已到达列表末尾。

  • 加载更多数据:到达列表末尾时,触发一个方法以使用 Volley 从服务器加载更多数据。更新您的数据源并通知适配器新数据。随着用户继续滚动,重复此过程。

程序

//MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

   private ArrayList<UserModal> userModalArrayList;
   private UserRVAdapter userRVAdapter;
   private RecyclerView userRV;
   private ProgressBar loadingPB;
   private NestedScrollView nestedSV;

   int page = 1; // Start from page 1
   int limit = 2;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      userModalArrayList = new ArrayList<>();

      userRV = findViewById(R.id.idRVUsers);
      loadingPB = findViewById(R.id.idPBLoading);
      nestedSV = findViewById(R.id.idNestedSV);

      userRVAdapter = new UserRVAdapter(userModalArrayList, 
MainActivity.this);
      userRV.setLayoutManager(new 
LinearLayoutManager(MainActivity.this));
      userRV.setAdapter(userRVAdapter);

      nestedSV.setOnScrollChangeListener(new 
NestedScrollView.OnScrollChangeListener
() {
         @Override
         public void onScrollChange(NestedScrollView v, 
int scrollX, int scrollY, int 
oldScrollX, int oldScrollY) {
            if (scrollY == v.getChildAt(0).
getMeasuredHeight() - 
v.getMeasuredHeight
()) {
               page++;
               loadingPB.setVisibility(View.VISIBLE);
               getDataFromAPI(page, limit);
            }
         }
      });

      getDataFromAPI(page, limit);
   }

   private void getDataFromAPI(int page, int limit) {
      if (page > limit) {
         Toast.makeText(this, "That's all the data..", 
Toast.LENGTH_SHORT).show();
         loadingPB.setVisibility(View.GONE);
         return;
      }

      String url = "https://reqres.in/api/users?page=" 
+ page;

      RequestQueue queue = Volley.newRequestQueue
(MainActivity.this);
      JsonObjectRequest jsonObjectRequest = 
new JsonObjectRequest(Request.Method.GET, 
url, null, new Response.Listener<JSONObject>() {
         @Override
         public void onResponse(JSONObject response) {
            try {
               JSONArray dataArray = response.getJSONArray("data");
               for (int i = 0; i < dataArray.length(); i++) {
                  JSONObject jsonObject = 
dataArray.getJSONObject(i);
                  userModalArrayList.add(new 
UserModal(jsonObject.getString("first_name"), 
jsonObject.getString("last_name"), jsonObject.getString("email"), 
jsonObject.getString("avatar")));
               }
               userRVAdapter.notifyDataSetChanged(); 
// Notify adapter of data change
            } catch (JSONException e) {
               e.printStackTrace();
            }
            loadingPB.setVisibility(View.GONE);
         }
      }, new Response.ErrorListener() {
         @Override
         public void onErrorResponse(VolleyError error) {
            Toast.makeText(MainActivity.this, "Fail to get data..
", Toast.
LENGTH_SHORT).show();
            loadingPB.setVisibility(View.GONE);
         }
      });
      queue.add(jsonObjectRequest);
   }
}

// activity_main.xml
<androidx.core.widget.NestedScrollView
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/idNestedSV"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

   <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical">

      <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/idRVUsers"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         android:nestedScrollingEnabled="false"
         tools:listitem="@layout/user_rv_item" />

      <ProgressBar
         android:id="@+id/idPBLoading"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:visibility="gone" />
   </LinearLayout>

</androidx.core.widget.NestedScrollView>

输出

“加载更多”按钮

使用此方法,将“加载更多”按钮作为 RecyclerView 中的最后一个项目添加。点击它后,onClickListener 生效,利用 Volley 从服务器请求额外的数据。新信息加入当前数据集并通知适配器中的任何更改。通过手动且刻意地按下按钮,用户可以确定何时加载其他数据,使用这种分页方法可以让他们拥有更多权力和控制力。

算法

  • 设置您的 RecyclerView 和 Adapter:与方法 1 相同。

  • 添加“加载更多”按钮:将按钮作为 RecyclerView 数据列表中的最后一个项目插入,点击该按钮将触发加载更多数据。

  • 处理按钮点击:在适配器的 onBindViewHolder() 方法中,检测当前位置是否为最后一个项目。如果是,则显示“加载更多”按钮并设置 OnClickListener,以便在点击按钮时使用 Volley 获取更多数据。

  • 加载更多数据:点击“加载更多”按钮时,使用 Volley 从服务器请求其他数据。将新数据附加到现有数据源并通知适配器数据集更改。

程序

// MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

   private ArrayList<UserModal> userModalArrayList;
   private UserRVAdapter userRVAdapter;
   private RecyclerView userRV;
   private ProgressBar loadingPB;
   private Button loadMoreButton;

   int page = 1; // Start from page 1
   int limit = 2;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      userModalArrayList = new ArrayList<>();

      userRV = findViewById(R.id.idRVUsers);
      loadingPB = findViewById(R.id.idPBLoading);
      loadMoreButton = findViewById(R.id.idBtnLoadMore);

      userRVAdapter = new UserRVAdapter(userModalArrayList, 
MainActivity.this);
      userRV.setLayoutManager(new 
LinearLayoutManager(MainActivity.this));
      userRV.setAdapter(userRVAdapter);

      loadMoreButton.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            loadMoreData();
         }
      });

      loadMoreData();
   }

   private void loadMoreData() {
      String url = "https://reqres.in/api/users?page=" + page;

      RequestQueue queue = 
Volley.newRequestQueue(MainActivity.this);
      JsonObjectRequest jsonObjectRequest = new 
JsonObjectRequest(Request.Method.GET, url, null, new 
Response.Listener<JSONObject>() {
         @Override
         public void onResponse(JSONObject response) {
            try {
               JSONArray dataArray = response.getJSONArray("data");
               for (int i = 0; i < dataArray.length(); i++) {
                  JSONObject jsonObject = 
dataArray.getJSONObject(i);
                  userModalArrayList.add(new 
UserModal(jsonObject.getString("first_name"), 
jsonObject.getString("last_name"), jsonObject.getString("email"), 
jsonObject.getString("avatar")));
               }
               userRVAdapter.notifyDataSetChanged(); // Notify 
adapter of data change
               page++;
               if (page > limit) {
                  loadMoreButton.setVisibility(View.GONE);
               }
            } catch (JSONException e) {
               e.printStackTrace();
            }
            loadingPB.setVisibility(View.GONE);
         }
      }, new Response.ErrorListener() {
         @Override
         public void onErrorResponse(VolleyError error) {
            Toast.makeText(MainActivity.this, "Failed to get 
data..", Toast.LENGTH_SHORT).show();
            loadingPB.setVisibility(View.GONE);
         }
      });
      queue.add(jsonObjectRequest);
   }
}

//activity_main.xml
<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="match_parent"
   android:orientation="vertical">

   <androidx.recyclerview.widget.RecyclerView
      android:id="@+id/idRVUsers"
      android:layout_width="match_parent"
      android:layout_height="0dp"
      android:layout_weight="1"
      tools:listitem="@layout/user_rv_item" />

   <Button
      android:id="@+id/idBtnLoadMore"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Load More"
      android:visibility="visible" />

   <ProgressBar
      android:id="@+id/idPBLoading"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:visibility="visible" />
</LinearLayout>

输出

结论

在本教程中,使用 Volley 在 Android RecyclerView 中实现分页提供了一种有效的解决方案,可以有效地处理大型数据集并增强用户体验。无论是通过无限滚动还是“加载更多”按钮,这些方法都允许动态加载数据,确保流畅滚动并最大限度地减少内存消耗。通过利用 Volley 网络请求和 RecyclerView 灵活性的强大功能,开发人员可以在其 Android 应用程序中创建响应迅速且无缝的分页体验。

更新于: 2023-07-27

2K+ 浏览量

开启您的 职业生涯

通过完成课程获得认证

开始学习
广告