Refactor: 优化个人主页和账户主页帖子加载逻辑
- 统一MyProfileViewModel和AccountProfileViewModel中的帖子加载逻辑,使用一致的pageSize。 - 在ProfileWrap和AccountProfileV2中传递正确的postCount。 - 在ProfileV3中改进了加载更多帖子的触发条件,确保在有更多数据时才触发加载。 - 修复了注册页面勾选协议和促销选项后,错误状态未清除的问题。 - 为DataLoader和ProfileV3中的滚动加载逻辑添加了详细日志,方便调试。
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.aiosman.ravenow.entity
|
package com.aiosman.ravenow.entity
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -22,30 +23,38 @@ abstract class DataLoader<T,ET> {
|
|||||||
suspend fun loadData(
|
suspend fun loadData(
|
||||||
extra: ET
|
extra: ET
|
||||||
) {
|
) {
|
||||||
|
Log.d("DataLoader", "loadData开始 - firstLoad: $firstLoad")
|
||||||
if (!firstLoad) {
|
if (!firstLoad) {
|
||||||
|
Log.d("DataLoader", "loadData跳过 - 非首次加载")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
firstLoad = false
|
firstLoad = false
|
||||||
|
Log.d("DataLoader", "调用fetchData - page: $page, pageSize: $pageSize")
|
||||||
val result = fetchData(page, pageSize, extra)
|
val result = fetchData(page, pageSize, extra)
|
||||||
list = result.list.toMutableList()
|
list = result.list.toMutableList()
|
||||||
this.page = page
|
this.page = page
|
||||||
this.total = result.total
|
this.total = result.total
|
||||||
this.pageSize = pageSize
|
this.pageSize = pageSize
|
||||||
this.hasNext = result.list.size == pageSize
|
this.hasNext = result.list.size == pageSize
|
||||||
|
Log.d("DataLoader", "loadData完成 - 数据量: ${list.size}, total: $total, hasNext: $hasNext")
|
||||||
onListChanged?.invoke(list)
|
onListChanged?.invoke(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun loadMore(extra: ET) {
|
suspend fun loadMore(extra: ET) {
|
||||||
if (firstLoad) {
|
if (firstLoad) {
|
||||||
|
Log.d("DataLoader", "loadMore跳过 - firstLoad为true")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!hasNext) {
|
if (!hasNext) {
|
||||||
|
Log.d("DataLoader", "loadMore跳过 - hasNext为false")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Log.d("DataLoader", "开始loadMore - 当前页: $page, 当前数据量: ${list.size}")
|
||||||
val result = fetchData(page + 1, pageSize, extra)
|
val result = fetchData(page + 1, pageSize, extra)
|
||||||
list.addAll(result.list)
|
list.addAll(result.list)
|
||||||
page += 1
|
page += 1
|
||||||
hasNext = result.list.size == pageSize
|
hasNext = result.list.size == pageSize
|
||||||
|
Log.d("DataLoader", "loadMore完成 - 新页: $page, 新数据量: ${list.size}, 本次获取: ${result.list.size}, hasNext: $hasNext")
|
||||||
onListChanged?.invoke(list)
|
onListChanged?.invoke(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ object MyProfileViewModel : ViewModel() {
|
|||||||
var moments by mutableStateOf<List<MomentEntity>>(emptyList())
|
var moments by mutableStateOf<List<MomentEntity>>(emptyList())
|
||||||
var agents by mutableStateOf<List<AgentEntity>>(emptyList())
|
var agents by mutableStateOf<List<AgentEntity>>(emptyList())
|
||||||
val momentLoader: MomentLoader = MomentLoader().apply {
|
val momentLoader: MomentLoader = MomentLoader().apply {
|
||||||
|
pageSize = 20 // 设置与后端一致的页面大小
|
||||||
onListChanged = {
|
onListChanged = {
|
||||||
moments = it
|
moments = it
|
||||||
}
|
}
|
||||||
@@ -84,7 +85,15 @@ object MyProfileViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun loadMoreMoment() {
|
fun loadMoreMoment() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
momentLoader.loadMore(extra = MomentLoaderExtraArgs(authorId = profile?.id))
|
profile?.let { profileData ->
|
||||||
|
try {
|
||||||
|
Log.d("MyProfileViewModel", "loadMoreMoment: 开始加载更多, 当前moments数量: ${moments.size}, hasNext: ${momentLoader.hasNext}")
|
||||||
|
momentLoader.loadMore(extra = MomentLoaderExtraArgs(authorId = profileData.id))
|
||||||
|
Log.d("MyProfileViewModel", "loadMoreMoment: 加载完成, 新的moments数量: ${moments.size}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("MyProfileViewModel", "loadMoreMoment: ", e)
|
||||||
|
}
|
||||||
|
} ?: Log.w("MyProfileViewModel", "loadMoreMoment: profile为null,无法加载更多")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.aiosman.ravenow.ui.index.tabs.profile
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@@ -104,6 +105,7 @@ fun ProfileV3(
|
|||||||
onLike: (MomentEntity) -> Unit = {},
|
onLike: (MomentEntity) -> Unit = {},
|
||||||
onComment: (MomentEntity) -> Unit = {},
|
onComment: (MomentEntity) -> Unit = {},
|
||||||
onAgentClick: (AgentEntity) -> Unit = {},
|
onAgentClick: (AgentEntity) -> Unit = {},
|
||||||
|
postCount: Int? = null, // 新增参数用于传递帖子总数
|
||||||
) {
|
) {
|
||||||
val model = MyProfileViewModel
|
val model = MyProfileViewModel
|
||||||
val state = rememberCollapsingToolbarScaffoldState()
|
val state = rememberCollapsingToolbarScaffoldState()
|
||||||
@@ -146,8 +148,25 @@ fun ProfileV3(
|
|||||||
// observe grid scrolling for load more
|
// observe grid scrolling for load more
|
||||||
val reachedGridBottom by remember {
|
val reachedGridBottom by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
val lastVisibleItem = gridState.layoutInfo.visibleItemsInfo.lastOrNull()
|
val layoutInfo = gridState.layoutInfo
|
||||||
lastVisibleItem?.index != 0 && lastVisibleItem?.index == gridState.layoutInfo.totalItemsCount - 2
|
val lastVisibleItem = layoutInfo.visibleItemsInfo.lastOrNull()
|
||||||
|
val totalItems = layoutInfo.totalItemsCount
|
||||||
|
val visibleItemsCount = layoutInfo.visibleItemsInfo.size
|
||||||
|
|
||||||
|
Log.d("ProfileV3", "滚动状态检查 - totalItems: $totalItems, visibleItems: $visibleItemsCount, lastVisibleIndex: ${lastVisibleItem?.index}, moments.size: ${moments.size}, hasNext: ${model.momentLoader.hasNext}")
|
||||||
|
|
||||||
|
// 如果没有可见item,不触发加载
|
||||||
|
if (lastVisibleItem == null || totalItems == 0) {
|
||||||
|
Log.d("ProfileV3", "跳过加载 - 没有可见item或总数为0")
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
// 检查是否滚动到最后几个item(考虑到有Spacer item)
|
||||||
|
// 当接近底部时提前触发加载
|
||||||
|
val triggerIndex = maxOf(0, totalItems - 2)
|
||||||
|
val result = lastVisibleItem.index >= triggerIndex && model.momentLoader.hasNext
|
||||||
|
Log.d("ProfileV3", "滚动检测结果 - lastVisibleIndex: ${lastVisibleItem.index}, triggerIndex: $triggerIndex, hasNext: ${model.momentLoader.hasNext}, shouldTrigger: $result")
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +179,9 @@ fun ProfileV3(
|
|||||||
|
|
||||||
// load more if scrolled to bottom of grid
|
// load more if scrolled to bottom of grid
|
||||||
LaunchedEffect(reachedGridBottom) {
|
LaunchedEffect(reachedGridBottom) {
|
||||||
|
Log.d("ProfileV3", "LaunchedEffect触发 - reachedGridBottom: $reachedGridBottom")
|
||||||
if (reachedGridBottom) {
|
if (reachedGridBottom) {
|
||||||
|
Log.d("ProfileV3", "检测到网格滚动到底部,触发加载更多")
|
||||||
onLoadMore()
|
onLoadMore()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,7 +349,7 @@ fun ProfileV3(
|
|||||||
profile?.let {
|
profile?.let {
|
||||||
UserItem(
|
UserItem(
|
||||||
accountProfileEntity = it,
|
accountProfileEntity = it,
|
||||||
postCount = moments.size
|
postCount = postCount ?: if (isSelf) MyProfileViewModel.momentLoader.total else moments.size
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.aiosman.ravenow.ui.index.tabs.profile
|
package com.aiosman.ravenow.ui.index.tabs.profile
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -17,6 +18,7 @@ fun ProfileWrap(
|
|||||||
}
|
}
|
||||||
ProfileV3(
|
ProfileV3(
|
||||||
isMain = true,
|
isMain = true,
|
||||||
|
postCount = MyProfileViewModel.momentLoader.total,
|
||||||
onUpdateBanner = { uri, file, context ->
|
onUpdateBanner = { uri, file, context ->
|
||||||
MyProfileViewModel.updateUserProfileBanner(uri, file, context)
|
MyProfileViewModel.updateUserProfileBanner(uri, file, context)
|
||||||
},
|
},
|
||||||
@@ -27,6 +29,7 @@ fun ProfileWrap(
|
|||||||
moments = MyProfileViewModel.moments,
|
moments = MyProfileViewModel.moments,
|
||||||
agents = MyProfileViewModel.agents,
|
agents = MyProfileViewModel.agents,
|
||||||
onLoadMore = {
|
onLoadMore = {
|
||||||
|
Log.d("ProfileWrap", "onLoadMore被调用")
|
||||||
MyProfileViewModel.loadMoreMoment()
|
MyProfileViewModel.loadMoreMoment()
|
||||||
},
|
},
|
||||||
onLike = { moments ->
|
onLike = { moments ->
|
||||||
|
|||||||
@@ -240,6 +240,10 @@ fun EmailSignupScreen() {
|
|||||||
error = termsError
|
error = termsError
|
||||||
) {
|
) {
|
||||||
acceptTerms = it
|
acceptTerms = it
|
||||||
|
// 当用户勾选时,立即清除错误状态
|
||||||
|
if (it) {
|
||||||
|
termsError = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
CheckboxWithLabel(
|
CheckboxWithLabel(
|
||||||
@@ -250,6 +254,10 @@ fun EmailSignupScreen() {
|
|||||||
error = promotionsError
|
error = promotionsError
|
||||||
) {
|
) {
|
||||||
acceptPromotions = it
|
acceptPromotions = it
|
||||||
|
// 当用户勾选时,立即清除错误状态
|
||||||
|
if (it) {
|
||||||
|
promotionsError = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.aiosman.ravenow.ui.profile
|
package com.aiosman.ravenow.ui.profile
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
@@ -8,6 +9,7 @@ import com.aiosman.ravenow.exp.viewModelFactory
|
|||||||
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
||||||
import com.aiosman.ravenow.ui.index.tabs.profile.ProfileV3
|
import com.aiosman.ravenow.ui.index.tabs.profile.ProfileV3
|
||||||
import com.aiosman.ravenow.ui.navigateToChat
|
import com.aiosman.ravenow.ui.navigateToChat
|
||||||
|
import com.aiosman.ravenow.ui.navigateToPost
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AccountProfileV2(id: String){
|
fun AccountProfileV2(id: String){
|
||||||
@@ -27,6 +29,17 @@ fun AccountProfileV2(id: String){
|
|||||||
moments = model.moments,
|
moments = model.moments,
|
||||||
profile = model.profile,
|
profile = model.profile,
|
||||||
isSelf = isSelf,
|
isSelf = isSelf,
|
||||||
|
postCount = model.momentLoader.total,
|
||||||
|
onLoadMore = {
|
||||||
|
Log.d("AccountProfileV2", "onLoadMore被调用")
|
||||||
|
model.loadMoreMoment()
|
||||||
|
},
|
||||||
|
onLike = { moment ->
|
||||||
|
// TODO: 实现点赞逻辑
|
||||||
|
},
|
||||||
|
onComment = { moment ->
|
||||||
|
navController.navigateToPost(moment.id)
|
||||||
|
},
|
||||||
onChatClick = {
|
onChatClick = {
|
||||||
model.profile?.let {
|
model.profile?.let {
|
||||||
navController.navigateToChat(it.id.toString())
|
navController.navigateToChat(it.id.toString())
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.aiosman.ravenow.ui.profile
|
package com.aiosman.ravenow.ui.profile
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -25,6 +26,7 @@ class AccountProfileViewModel : ViewModel() {
|
|||||||
var profile by mutableStateOf<AccountProfileEntity?>(null)
|
var profile by mutableStateOf<AccountProfileEntity?>(null)
|
||||||
var refreshing by mutableStateOf(false)
|
var refreshing by mutableStateOf(false)
|
||||||
var momentLoader = MomentLoader().apply {
|
var momentLoader = MomentLoader().apply {
|
||||||
|
pageSize = 20 // 设置与后端一致的页面大小
|
||||||
onListChanged = {
|
onListChanged = {
|
||||||
moments = it
|
moments = it
|
||||||
}
|
}
|
||||||
@@ -58,6 +60,21 @@ class AccountProfileViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadMoreMoment() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
profile?.let { profileData ->
|
||||||
|
try {
|
||||||
|
Log.d("AccountProfileViewModel", "loadMoreMoment: 开始加载更多, 当前moments数量: ${moments.size}, hasNext: ${momentLoader.hasNext}")
|
||||||
|
momentLoader.loadMore(extra = MomentLoaderExtraArgs(authorId = profileData.id))
|
||||||
|
Log.d("AccountProfileViewModel", "loadMoreMoment: 加载完成, 新的moments数量: ${moments.size}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("AccountProfileViewModel", "loadMoreMoment: ", e)
|
||||||
|
}
|
||||||
|
} ?: Log.w("AccountProfileViewModel", "loadMoreMoment: profile为null,无法加载更多")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onFollowChangeEvent(event: FollowChangeEvent) {
|
fun onFollowChangeEvent(event: FollowChangeEvent) {
|
||||||
if (event.userId == profile?.id) {
|
if (event.userId == profile?.id) {
|
||||||
|
|||||||
Reference in New Issue
Block a user