From c8383af120b7686f337cbe8ec7a5d6bc05de30df Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Fri, 5 Jun 2026 10:13:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(meal):=20=E6=B7=BB=E5=8A=A0=E9=A4=90?= =?UTF-8?q?=E5=93=81=E5=88=97=E8=A1=A8=E4=B8=8B=E6=8B=89=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E5=92=8C=E4=B8=8A=E6=8B=89=E5=8A=A0=E8=BD=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 集成 SmartRefreshLayout 实现下拉刷新和上拉加载更多 - 修改 MealListActivity 添加分页加载逻辑,每页30条数据 - 实现空视图显示功能,当无数据时展示暂无数据提示 - 优化 RecyclerView 点击事件处理,使用 startActivity 扩展函数 - 添加加载状态管理,区分首次加载和后续加载情况 - 实现加载失败时的状态回退和错误处理机制 - 统一网络请求回调处理,优化 Loading 状态显示逻辑 --- .../shuwei/dish/match/net/NetViewModelV2.kt | 3 +- .../shuwei/dish/match/ui/MealListActivity.kt | 87 +++++++++++++++---- .../main/res/layout/activity_meal_list.xml | 31 +++++-- 3 files changed, 96 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/shuwei/dish/match/net/NetViewModelV2.kt b/app/src/main/java/com/shuwei/dish/match/net/NetViewModelV2.kt index 07dcb20..7d4a541 100644 --- a/app/src/main/java/com/shuwei/dish/match/net/NetViewModelV2.kt +++ b/app/src/main/java/com/shuwei/dish/match/net/NetViewModelV2.kt @@ -114,7 +114,8 @@ class NetViewModelV2( ) { viewModelScope.launch { onLoading() - onResult(repository.getFoodOptions(keyword, pageNum, pageSize)) + val state = repository.getFoodOptions(keyword, pageNum, pageSize) + onResult(state) } } diff --git a/app/src/main/java/com/shuwei/dish/match/ui/MealListActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/MealListActivity.kt index ea0a2ed..4b4c58c 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/MealListActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/MealListActivity.kt @@ -2,14 +2,17 @@ package com.shuwei.dish.match.ui import android.content.Intent import android.os.Bundle +import android.view.LayoutInflater import androidx.recyclerview.widget.LinearLayoutManager import com.shuwei.dish.match.adapter.MealListAdapter import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.databinding.ActivityMealListBinding +import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding import com.shuwei.dish.match.model.NutFoodOptionVO import com.shuwei.dish.match.net.NetViewModelV2 import com.shuwei.dish.match.net.UiState import com.shuwei.dish.match.utils.ext.gone +import com.shuwei.dish.match.utils.ext.startActivity import com.shuwei.dish.match.utils.ext.toast import com.shuwei.dish.match.utils.ext.visible @@ -20,13 +23,24 @@ class MealListActivity : BaseActivity() { companion object { const val MEAL_ITEM = "mealItem" + const val PAGE_SIZE = 30 } private val binding by lazy { ActivityMealListBinding.inflate(layoutInflater) } private val viewModelV2 by lazy { NetViewModelV2() } private val mealList = mutableListOf() - private val mealAdapter by lazy { MealListAdapter(mealList) } + private val mealAdapter by lazy { MealListAdapter(mealList).apply { + isStateViewEnable = true + setOnItemClickListener { _, _, position -> + val item = mealList.getOrNull(position) ?: return@setOnItemClickListener + startActivity{ + putExtra(PackActivity.MEAL_ITEM, item) + } + } + } } + private var emptyViewBinding: LayoutEmptyViewBinding? = null + private var currentPage = 1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -54,12 +68,15 @@ class MealListActivity : BaseActivity() { private fun initRecyclerView() { binding.rvMealList.layoutManager = LinearLayoutManager(this) binding.rvMealList.adapter = mealAdapter - mealAdapter.setOnItemClickListener { _, _, position -> - val item = mealList.getOrNull(position) ?: return@setOnItemClickListener - val intent = Intent(this, PackActivity::class.java).apply { - putExtra(PackActivity.MEAL_ITEM, item) - } - startActivity(intent) + binding.refreshLayout.setEnableRefresh(true) + binding.refreshLayout.setEnableLoadMore(true) + binding.refreshLayout.setOnRefreshListener { + currentPage = 1 + loadMealList() + } + binding.refreshLayout.setOnLoadMoreListener { + currentPage++ + loadMealList() } } @@ -67,32 +84,70 @@ class MealListActivity : BaseActivity() { * 加载餐品列表 */ private fun loadMealList() { + showLoading("加载中……") viewModelV2.getFoodOptionsWithCallback( keyword = null, - pageNum = 1, - pageSize = 100, - onLoading = { - showLoading("加载中……") - }, + pageNum = currentPage, + pageSize = PAGE_SIZE, + onLoading = {}, onResult = { state -> dismissLoading() when (state) { is UiState.Success -> { val records = state.data?.records - if (records.isNullOrEmpty()) { - toast("暂无数据") + if (currentPage == 1 && records.isNullOrEmpty()) { + binding.refreshLayout.finishRefresh() + loadEmptyView() return@getFoodOptionsWithCallback } - mealList.clear() - mealList.addAll(records) + if (currentPage == 1) { + mealList.clear() + } + mealList.addAll(records!!) mealAdapter.notifyDataSetChanged() + val isLoadMore = records.size >= PAGE_SIZE + binding.refreshLayout.setEnableLoadMore(isLoadMore) + if (isLoadMore) { + binding.refreshLayout.finishLoadMore() + } else { + binding.refreshLayout.finishLoadMoreWithNoMoreData() + } } is UiState.Error -> { toast(state.msg) + if (currentPage == 1) { + binding.refreshLayout.finishRefresh() + loadEmptyView() + } else { + currentPage-- + binding.refreshLayout.finishLoadMore() + } } else -> {} } } ) } + + /** + * 加载空视图 + */ + private fun loadEmptyView() { + mealList.clear() + mealAdapter.notifyDataSetChanged() + if (emptyViewBinding == null) { + emptyViewBinding = LayoutEmptyViewBinding.inflate( + LayoutInflater.from(this), binding.rvMealList, false + ) + } + emptyViewBinding?.run { + tvContent.text = "暂无数据" + tvSubContent.text = "暂无餐品数据" + mealAdapter.stateView = root + } + binding.refreshLayout.run { + setEnableRefresh(true) + setEnableLoadMore(false) + } + } } diff --git a/app/src/main/res/layout/activity_meal_list.xml b/app/src/main/res/layout/activity_meal_list.xml index dcc05e8..deacd7e 100644 --- a/app/src/main/res/layout/activity_meal_list.xml +++ b/app/src/main/res/layout/activity_meal_list.xml @@ -26,15 +26,30 @@ android:textColor="@color/black666" android:textSize="28sp" /> - + android:layout_height="match_parent"> + + + + + + + +