You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit+RecyclerView数据加载:展示指定条数及实现加载更多

Q1: How to Display the First 10 Records in RecyclerView via Retrofit

Hey there! Let's walk through this step by step—it's straightforward once you break it down:

  • 1. Set Up Retrofit & Define Your API Interface
    First, make sure you have Retrofit and a JSON converter (like Gson Converter) added to your build config. Then create an API interface that accepts pagination parameters to fetch exactly 10 records. For example:

    interface ApiService {
        @GET("your-data-endpoint")
        suspend fun getRecords(
            @Query("page") page: Int = 1,
            @Query("limit") limit: Int = 10
        ): Response<RecordResponse>
    }
    

    We default to page=1 and limit=10 here to grab the first batch of records.

  • 2. Create Data Models
    Map the API's JSON response to a data class (Kotlin) or Java Bean. Keep it aligned with the structure your API returns:

    data class RecordResponse(val data: List<Record>)
    data class Record(val id: Int, val title: String, val description: String)
    
  • 3. Configure RecyclerView & Adapter
    Build a RecyclerView.Adapter and ViewHolder to render your records. The adapter will hold a mutable list of Record objects:

    class RecordAdapter(private val records: MutableList<Record>) : RecyclerView.Adapter<RecordAdapter.RecordViewHolder>() {
        inner class RecordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            fun bind(record: Record) {
                itemView.tv_title.text = record.title
                itemView.tv_description.text = record.description
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecordViewHolder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.item_record, parent, false)
            return RecordViewHolder(view)
        }
    
        override fun onBindViewHolder(holder: RecordViewHolder, position: Int) {
            holder.bind(records[position])
        }
    
        override fun getItemCount(): Int = records.size
    }
    
  • 4. Fetch & Display Data
    In your Activity/Fragment, initialize Retrofit, call the API, and update the RecyclerView once you get the data. Using Kotlin Coroutines for clean async calls:

    class MainActivity : AppCompatActivity() {
        private lateinit var adapter: RecordAdapter
        private val records = mutableListOf<Record>()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // Set up RecyclerView
            recyclerView.layoutManager = LinearLayoutManager(this)
            adapter = RecordAdapter(records)
            recyclerView.adapter = adapter
    
            // Fetch first 10 records
            lifecycleScope.launch {
                fetchInitialRecords()
            }
        }
    
        private suspend fun fetchInitialRecords() {
            val apiService = Retrofit.Builder()
                .baseUrl("https://your-api-base-url.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(ApiService::class.java)
    
            try {
                val response = apiService.getRecords()
                if (response.isSuccessful) {
                    response.body()?.data?.let {
                        records.clear()
                        records.addAll(it)
                        adapter.notifyDataSetChanged()
                    }
                }
            } catch (e: Exception) {
                // Handle error (show toast, log, etc.)
                e.printStackTrace()
            }
        }
    }
    

Q2: Add Load More Button to Fetch Next 10 Records (Already Displaying 20)

Great question—adding a load more button is a common pattern, and here's how to implement it smoothly:

  • 1. Confirm API Pagination Support
    You probably already have page and limit parameters set up (since you fetched 20 records). We’ll increment the page number each time we load more, keeping limit=10 to grab the next batch.

  • 2. Modify Adapter to Include Load More View
    Add a new view type for the load more button, and update the adapter to handle it:

    class RecordAdapter(
        private val records: MutableList<Record>,
        private val onLoadMoreClicked: () -> Unit
    ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
        private val VIEW_TYPE_RECORD = 0
        private val VIEW_TYPE_LOAD_MORE = 1
        private var isLoading = false
    
        fun setLoadingState(loading: Boolean) {
            isLoading = loading
            notifyItemChanged(records.size)
        }
    
        inner class RecordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            fun bind(record: Record) {
                itemView.tv_title.text = record.title
                itemView.tv_description.text = record.description
            }
        }
    
        inner class LoadMoreViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            init {
                itemView.btn_load_more.setOnClickListener {
                    if (!isLoading) onLoadMoreClicked.invoke()
                }
            }
        }
    
        override fun getItemViewType(position: Int): Int {
            return if (position == records.size) VIEW_TYPE_LOAD_MORE else VIEW_TYPE_RECORD
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return if (viewType == VIEW_TYPE_RECORD) {
                val view = LayoutInflater.from(parent.context).inflate(R.layout.item_record, parent, false)
                RecordViewHolder(view)
            } else {
                val view = LayoutInflater.from(parent.context).inflate(R.layout.item_load_more, parent, false)
                LoadMoreViewHolder(view)
            }
        }
    
        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            if (holder is RecordViewHolder) {
                holder.bind(records[position])
            } else if (holder is LoadMoreViewHolder) {
                // Update button text based on loading state
                holder.itemView.btn_load_more.text = if (isLoading) "Loading..." else "Load More"
                holder.itemView.btn_load_more.isEnabled = !isLoading
            }
        }
    
        override fun getItemCount(): Int = records.size + 1 // +1 for the load more item
    }
    

    Note: Create a layout item_load_more.xml with a Button (or ProgressBar + Button) for the load more action.

  • 3. Handle Load More in Activity/Fragment
    Track the current page number, and when the button is clicked, fetch the next page and append the data:

    class MainActivity : AppCompatActivity() {
        private lateinit var adapter: RecordAdapter
        private val records = mutableListOf<Record>()
        private var currentPage = 3 // Since you already have 20 records (pages 1 + 2, 10 each)
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // Assume records already contain 20 items here
            recyclerView.layoutManager = LinearLayoutManager(this)
            adapter = RecordAdapter(records) {
                lifecycleScope.launch { loadMoreRecords() }
            }
            recyclerView.adapter = adapter
        }
    
        private suspend fun loadMoreRecords() {
            adapter.setLoadingState(true)
            val apiService = Retrofit.Builder()
                .baseUrl("https://your-api-base-url.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(ApiService::class.java)
    
            try {
                val response = apiService.getRecords(currentPage, 10)
                if (response.isSuccessful) {
                    response.body()?.data?.let { newRecords ->
                        val startPosition = records.size
                        records.addAll(newRecords)
                        adapter.notifyItemRangeInserted(startPosition, newRecords.size)
                        currentPage++
    
                        // If no more records, hide the load more item or update text
                        if (newRecords.isEmpty()) {
                            // Example: adapter.removeLoadMoreItem() (add this method to adapter if needed)
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                adapter.setLoadingState(false)
            }
        }
    }
    
  • 4. Key Considerations

    • Use the isLoading flag to prevent duplicate requests while fetching data.
    • Handle edge cases: if there are no more records, hide the load more button or change its text to "No More Records".
    • Use notifyItemRangeInserted instead of notifyDataSetChanged for better RecyclerView performance.

内容的提问来源于stack exchange,提问作者jeetdeveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:44:50