如何在 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+ 瀏覽量

開啟您的 職業生涯

透過完成課程獲得認證

開始學習
廣告