feat(meal): 添加餐品列表下拉刷新和上拉加载功能
- 集成 SmartRefreshLayout 实现下拉刷新和上拉加载更多 - 修改 MealListActivity 添加分页加载逻辑,每页30条数据 - 实现空视图显示功能,当无数据时展示暂无数据提示 - 优化 RecyclerView 点击事件处理,使用 startActivity 扩展函数 - 添加加载状态管理,区分首次加载和后续加载情况 - 实现加载失败时的状态回退和错误处理机制 - 统一网络请求回调处理,优化 Loading 状态显示逻辑
This commit is contained in:
@@ -114,7 +114,8 @@ class NetViewModelV2(
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
onLoading()
|
||||
onResult(repository.getFoodOptions(keyword, pageNum, pageSize))
|
||||
val state = repository.getFoodOptions(keyword, pageNum, pageSize)
|
||||
onResult(state)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<NutFoodOptionVO>()
|
||||
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<PackActivity>{
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,15 +26,30 @@
|
||||
android:textColor="@color/black666"
|
||||
android:textSize="28sp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvMealList"
|
||||
<com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="vertical"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/list_item_food2" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.scwang.smart.refresh.header.ClassicsHeader
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvMealList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="vertical"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/list_item_food2" />
|
||||
|
||||
<com.scwang.smart.refresh.footer.ClassicsFooter
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user