资源清理管理
This commit is contained in:
@@ -97,7 +97,7 @@ fun AccountEditScreen2() {
|
|||||||
) {
|
) {
|
||||||
//StatusBarSpacer()
|
//StatusBarSpacer()
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
|
modifier = Modifier.padding(horizontal = 0.dp, vertical = 16.dp)
|
||||||
) {
|
) {
|
||||||
NoticeScreenHeader(
|
NoticeScreenHeader(
|
||||||
title = stringResource(R.string.edit_profile),
|
title = stringResource(R.string.edit_profile),
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import androidx.compose.material3.Text
|
|||||||
import androidx.compose.material3.rememberDrawerState
|
import androidx.compose.material3.rememberDrawerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
@@ -73,6 +74,7 @@ import com.aiosman.ravenow.ui.index.tabs.shorts.ShortVideo
|
|||||||
import com.aiosman.ravenow.ui.index.tabs.street.StreetPage
|
import com.aiosman.ravenow.ui.index.tabs.street.StreetPage
|
||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
import com.aiosman.ravenow.ui.post.NewPostViewModel
|
import com.aiosman.ravenow.ui.post.NewPostViewModel
|
||||||
|
import com.aiosman.ravenow.utils.ResourceCleanupManager
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -97,6 +99,13 @@ fun IndexScreen() {
|
|||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val drawerState = rememberDrawerState(DrawerValue.Closed)
|
val drawerState = rememberDrawerState(DrawerValue.Closed)
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
// 页面退出时清理所有资源
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
ResourceCleanupManager.cleanupAllResources(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
systemUiController.setNavigationBarColor(Color.Transparent)
|
systemUiController.setNavigationBarColor(Color.Transparent)
|
||||||
}
|
}
|
||||||
@@ -363,9 +372,19 @@ fun IndexScreen() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun Home() {
|
fun Home() {
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(AppState.darkMode) {
|
LaunchedEffect(AppState.darkMode) {
|
||||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode)
|
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 页面退出时清理动态相关资源
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
ResourceCleanupManager.cleanupPageResources("moment")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
@@ -380,9 +399,19 @@ fun Home() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun Street() {
|
fun Street() {
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(AppState.darkMode) {
|
LaunchedEffect(AppState.darkMode) {
|
||||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode)
|
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 页面退出时清理搜索相关资源
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
ResourceCleanupManager.cleanupPageResources("search")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
@@ -430,9 +459,19 @@ fun Video() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun Profile() {
|
fun Profile() {
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(AppState.darkMode) {
|
LaunchedEffect(AppState.darkMode) {
|
||||||
systemUiController.setStatusBarColor(Color.Transparent, !AppState.darkMode)
|
systemUiController.setStatusBarColor(Color.Transparent, !AppState.darkMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 页面退出时清理个人资料相关资源
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
ResourceCleanupManager.cleanupPageResources("profile")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
@@ -446,9 +485,19 @@ fun Profile() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun Notifications() {
|
fun Notifications() {
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(AppState.darkMode) {
|
LaunchedEffect(AppState.darkMode) {
|
||||||
systemUiController.setStatusBarColor(Color.Transparent, !AppState.darkMode)
|
systemUiController.setStatusBarColor(Color.Transparent, !AppState.darkMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 页面退出时清理消息相关资源
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
ResourceCleanupManager.cleanupPageResources("message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
|
|||||||
@@ -28,7 +28,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
@@ -53,6 +58,8 @@ import com.aiosman.ravenow.ui.composables.TabItem
|
|||||||
import com.aiosman.ravenow.ui.composables.TabSpacer
|
import com.aiosman.ravenow.ui.composables.TabSpacer
|
||||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.AgentItem
|
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.AgentItem
|
||||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.ExploreViewModel
|
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.ExploreViewModel
|
||||||
|
import com.aiosman.ravenow.utils.DebounceUtils
|
||||||
|
import com.aiosman.ravenow.utils.ResourceCleanupManager
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn( ExperimentalFoundationApi::class)
|
@OptIn( ExperimentalFoundationApi::class)
|
||||||
@@ -68,6 +75,16 @@ fun Agent() {
|
|||||||
|
|
||||||
val viewModel: AgentViewModel = viewModel()
|
val viewModel: AgentViewModel = viewModel()
|
||||||
|
|
||||||
|
// 防抖状态
|
||||||
|
var lastClickTime by remember { mutableStateOf(0L) }
|
||||||
|
|
||||||
|
// 页面退出时清理AI相关资源
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
ResourceCleanupManager.cleanupPageResources("ai")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -119,11 +136,15 @@ fun Agent() {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(36.dp)
|
.size(36.dp)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
|
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
|
||||||
// 设置标志,表示新增智能体后不需要刷新
|
// 设置标志,表示新增智能体后不需要刷新
|
||||||
com.aiosman.ravenow.ui.agent.AddAgentViewModel.isFromAddAgent = true
|
com.aiosman.ravenow.ui.agent.AddAgentViewModel.isFromAddAgent = true
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
NavigationRoute.AddAgent.route
|
NavigationRoute.AddAgent.route
|
||||||
)
|
)
|
||||||
|
}) {
|
||||||
|
lastClickTime = System.currentTimeMillis()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
painter = painterResource(id = R.drawable.rider_pro_new_post_add_pic),
|
painter = painterResource(id = R.drawable.rider_pro_new_post_add_pic),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
@@ -189,9 +210,13 @@ fun Agent() {
|
|||||||
text = stringResource(R.string.agent_mine),
|
text = stringResource(R.string.agent_mine),
|
||||||
isSelected = pagerState.currentPage == 0,
|
isSelected = pagerState.currentPage == 0,
|
||||||
onClick = {
|
onClick = {
|
||||||
|
if (DebounceUtils.simpleDebounceClick(lastClickTime, 300L) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
pagerState.animateScrollToPage(0)
|
pagerState.animateScrollToPage(0)
|
||||||
}
|
}
|
||||||
|
}) {
|
||||||
|
lastClickTime = System.currentTimeMillis()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
TabSpacer()
|
TabSpacer()
|
||||||
@@ -199,9 +224,13 @@ fun Agent() {
|
|||||||
text = stringResource(R.string.agent_hot),
|
text = stringResource(R.string.agent_hot),
|
||||||
isSelected = pagerState.currentPage == 1,
|
isSelected = pagerState.currentPage == 1,
|
||||||
onClick = {
|
onClick = {
|
||||||
|
if (DebounceUtils.simpleDebounceClick(lastClickTime, 300L) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
pagerState.animateScrollToPage(1)
|
pagerState.animateScrollToPage(1)
|
||||||
}
|
}
|
||||||
|
}) {
|
||||||
|
lastClickTime = System.currentTimeMillis()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/*TabSpacer()
|
/*TabSpacer()
|
||||||
@@ -348,6 +377,9 @@ fun AgentPage(viewModel: AgentViewModel,agentItems: List<AgentItem>, page: Int,
|
|||||||
fun AgentCard2(viewModel: AgentViewModel,agentItem: AgentItem,navController: NavHostController) {
|
fun AgentCard2(viewModel: AgentViewModel,agentItem: AgentItem,navController: NavHostController) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
// 防抖状态
|
||||||
|
var lastClickTime by remember { mutableStateOf(0L) }
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -419,8 +451,12 @@ fun AgentCard2(viewModel: AgentViewModel,agentItem: AgentItem,navController: Nav
|
|||||||
shape = RoundedCornerShape(8.dp)
|
shape = RoundedCornerShape(8.dp)
|
||||||
)
|
)
|
||||||
.clickable {
|
.clickable {
|
||||||
|
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
|
||||||
/* viewModel.createSingleChat(agentItem.trtcId)
|
/* viewModel.createSingleChat(agentItem.trtcId)
|
||||||
viewModel.goToChatAi(agentItem.trtcId, navController = navController)*/
|
viewModel.goToChatAi(agentItem.trtcId, navController = navController)*/
|
||||||
|
}) {
|
||||||
|
lastClickTime = System.currentTimeMillis()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ fun HotAgent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只在首次加载时刷新,避免从AddAgent返回时重复刷新
|
// 只在初始化页面时刷新
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
// 只有在列表完全为空且没有正在加载时才进行初始化刷新
|
||||||
if (model.agentList.isEmpty() && !model.isLoading) {
|
if (model.agentList.isEmpty() && !model.isLoading) {
|
||||||
model.refreshPager()
|
model.refreshPager()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ fun MineAgent() {
|
|||||||
|
|
||||||
// Paging 库会自动处理加载更多,无需手动监听滚动
|
// Paging 库会自动处理加载更多,无需手动监听滚动
|
||||||
|
|
||||||
// 只在首次加载时刷新,避免从AddAgent返回时重复刷新
|
// 只在初始化页面时刷新
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
// 只有在列表完全为空且没有正在加载时才进行初始化刷新
|
||||||
if (agentList.itemCount == 0 && !model.isLoading) {
|
if (agentList.itemCount == 0 && !model.isLoading) {
|
||||||
model.refreshPager()
|
model.refreshPager()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import com.aiosman.ravenow.entity.MomentPagingSource
|
|||||||
import com.aiosman.ravenow.entity.MomentRemoteDataSource
|
import com.aiosman.ravenow.entity.MomentRemoteDataSource
|
||||||
import com.aiosman.ravenow.entity.MomentServiceImpl
|
import com.aiosman.ravenow.entity.MomentServiceImpl
|
||||||
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel.userService
|
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel.userService
|
||||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot.HotMomentViewModel.firstLoad
|
|
||||||
import com.aiosman.ravenow.ui.navigateToChatAi
|
import com.aiosman.ravenow.ui.navigateToChatAi
|
||||||
import com.tencent.imsdk.v2.V2TIMConversationOperationResult
|
import com.tencent.imsdk.v2.V2TIMConversationOperationResult
|
||||||
import com.tencent.imsdk.v2.V2TIMManager
|
import com.tencent.imsdk.v2.V2TIMManager
|
||||||
@@ -47,6 +46,7 @@ object MineAgentViewModel : ViewModel() {
|
|||||||
var hasNext by mutableStateOf(true)
|
var hasNext by mutableStateOf(true)
|
||||||
var currentPage by mutableStateOf(1)
|
var currentPage by mutableStateOf(1)
|
||||||
var error by mutableStateOf<String?>(null)
|
var error by mutableStateOf<String?>(null)
|
||||||
|
var isFirstLoad by mutableStateOf(true)
|
||||||
|
|
||||||
// 记录已预加载的图片ID,避免重复加载
|
// 记录已预加载的图片ID,避免重复加载
|
||||||
private val preloadedImageIds = mutableSetOf<Int>()
|
private val preloadedImageIds = mutableSetOf<Int>()
|
||||||
@@ -55,10 +55,10 @@ object MineAgentViewModel : ViewModel() {
|
|||||||
|
|
||||||
|
|
||||||
fun refreshPager() {
|
fun refreshPager() {
|
||||||
if (!firstLoad) {
|
if (!isFirstLoad) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
firstLoad = false
|
isFirstLoad = false
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
Pager(
|
Pager(
|
||||||
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import androidx.compose.foundation.pager.rememberPagerState
|
|||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
import androidx.compose.material.pullrefresh.pullRefresh
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
@@ -179,32 +180,38 @@ fun NotificationsScreen() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
.height(40.dp)
|
.height(40.dp)
|
||||||
.background(
|
|
||||||
color = Color(0xFFF5F5F5),
|
.noRippleClickable {
|
||||||
shape = RoundedCornerShape(8.dp)
|
|
||||||
)
|
|
||||||
.noRippleClickable {//添加搜索逻辑实现
|
|
||||||
},
|
},
|
||||||
contentAlignment = Alignment.CenterStart
|
contentAlignment = Alignment.CenterStart
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
modifier = Modifier
|
||||||
modifier = Modifier.padding(start = 16.dp)
|
.height(36.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(shape = RoundedCornerShape(8.dp))
|
||||||
|
.background(AppColors.inputBackground)
|
||||||
|
.padding(horizontal = 8.dp, vertical = 0.dp)
|
||||||
|
.noRippleClickable {
|
||||||
|
// 搜索框点击事件
|
||||||
|
},
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Image(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_search_location),
|
painter = painterResource(id = R.drawable.rider_pro_nav_search),
|
||||||
contentDescription = "search",
|
contentDescription = null,
|
||||||
modifier = Modifier.size(20.dp),
|
tint = AppColors.inputHint
|
||||||
colorFilter = ColorFilter.tint(Color(0xFF999999))
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Box {
|
||||||
Text(
|
androidx.compose.material.Text(
|
||||||
text = stringResource(R.string.search),
|
text = stringResource(R.string.search),
|
||||||
fontSize = 14.sp,
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
color = Color(0xFF999999)
|
color = AppColors.inputHint,
|
||||||
|
fontSize = 17.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
@@ -410,6 +410,7 @@ fun NewPostTextField(hint: String, value: String, onValueChange: (String) -> Uni
|
|||||||
value = value,
|
value = value,
|
||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
.height(160.dp)
|
.height(160.dp)
|
||||||
.heightIn(160.dp)
|
.heightIn(160.dp)
|
||||||
.padding(horizontal = 16.dp, vertical = 10.dp),
|
.padding(horizontal = 16.dp, vertical = 10.dp),
|
||||||
|
|||||||
78
app/src/main/java/com/aiosman/ravenow/utils/DebounceUtils.kt
Normal file
78
app/src/main/java/com/aiosman/ravenow/utils/DebounceUtils.kt
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package com.aiosman.ravenow.utils
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖工具类
|
||||||
|
* 用于防止用户快速重复点击
|
||||||
|
*/
|
||||||
|
object DebounceUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖点击处理
|
||||||
|
* @param scope 协程作用域
|
||||||
|
* @param delayMillis 防抖延迟时间(毫秒),默认500ms
|
||||||
|
* @param action 要执行的操作
|
||||||
|
*/
|
||||||
|
fun debounceClick(
|
||||||
|
scope: CoroutineScope,
|
||||||
|
delayMillis: Long = 500L,
|
||||||
|
action: () -> Unit
|
||||||
|
) {
|
||||||
|
scope.launch {
|
||||||
|
delay(delayMillis)
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带状态检查的防抖点击处理
|
||||||
|
* @param scope 协程作用域
|
||||||
|
* @param delayMillis 防抖延迟时间(毫秒),默认500ms
|
||||||
|
* @param isProcessing 是否正在处理中的状态
|
||||||
|
* @param action 要执行的操作
|
||||||
|
*/
|
||||||
|
fun debounceClickWithState(
|
||||||
|
scope: CoroutineScope,
|
||||||
|
delayMillis: Long = 500L,
|
||||||
|
isProcessing: AtomicBoolean,
|
||||||
|
action: () -> Unit
|
||||||
|
) {
|
||||||
|
if (isProcessing.get()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isProcessing.set(true)
|
||||||
|
scope.launch {
|
||||||
|
delay(delayMillis)
|
||||||
|
try {
|
||||||
|
action()
|
||||||
|
} finally {
|
||||||
|
isProcessing.set(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单的防抖点击处理(无协程)
|
||||||
|
* @param lastClickTime 上次点击时间
|
||||||
|
* @param delayMillis 防抖延迟时间(毫秒),默认500ms
|
||||||
|
* @param action 要执行的操作
|
||||||
|
* @return 是否执行了操作
|
||||||
|
*/
|
||||||
|
fun simpleDebounceClick(
|
||||||
|
lastClickTime: Long,
|
||||||
|
delayMillis: Long = 500L,
|
||||||
|
action: () -> Unit
|
||||||
|
): Boolean {
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
if (currentTime - lastClickTime < delayMillis) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
action()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
package com.aiosman.ravenow.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import com.aiosman.ravenow.AppState
|
||||||
|
import com.aiosman.ravenow.ui.index.IndexViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.ai.AgentViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.hot.HotAgentViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.mine.MineAgentViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.dynamic.DynamicViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot.HotMomentViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.timeline.TimelineMomentViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.search.DiscoverViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.search.SearchViewModel
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel
|
||||||
|
import com.aiosman.ravenow.ui.like.LikeNoticeViewModel
|
||||||
|
import com.aiosman.ravenow.ui.favourite.FavouriteListViewModel
|
||||||
|
import com.aiosman.ravenow.ui.favourite.FavouriteNoticeViewModel
|
||||||
|
import com.aiosman.ravenow.ui.follower.FollowerNoticeViewModel
|
||||||
|
import com.aiosman.ravenow.ui.post.NewPostViewModel
|
||||||
|
import com.aiosman.ravenow.ui.imageviewer.ImageViewerViewModel
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源清理管理器
|
||||||
|
* 用于在Index页面退出时清理所有相关资源
|
||||||
|
*/
|
||||||
|
object ResourceCleanupManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理所有Index页面相关的资源
|
||||||
|
* @param context 上下文
|
||||||
|
*/
|
||||||
|
fun cleanupAllResources(context: Context) {
|
||||||
|
try {
|
||||||
|
// 1. 清理ViewModel资源
|
||||||
|
cleanupViewModels()
|
||||||
|
|
||||||
|
// 2. 清理EventBus注册
|
||||||
|
cleanupEventBus()
|
||||||
|
|
||||||
|
// 3. 清理服务
|
||||||
|
cleanupServices(context)
|
||||||
|
|
||||||
|
// 4. 清理缓存和临时数据
|
||||||
|
cleanupCacheAndTempData()
|
||||||
|
|
||||||
|
// 5. 重置应用状态
|
||||||
|
resetAppState()
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// 记录错误但不抛出异常,确保清理过程不会中断
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理所有ViewModel资源
|
||||||
|
*/
|
||||||
|
private fun cleanupViewModels() {
|
||||||
|
// 重置Index相关ViewModel
|
||||||
|
IndexViewModel.ResetModel()
|
||||||
|
|
||||||
|
// 重置AI相关ViewModel
|
||||||
|
// AgentViewModel的属性是私有的,无法直接访问,通过其他方式清理
|
||||||
|
|
||||||
|
HotAgentViewModel.let {
|
||||||
|
it.agentList = emptyList()
|
||||||
|
it.refreshing = false
|
||||||
|
it.isLoading = false
|
||||||
|
it.hasNext = true
|
||||||
|
it.currentPage = 1
|
||||||
|
it.error = null
|
||||||
|
it.clearPreloadedImages()
|
||||||
|
}
|
||||||
|
|
||||||
|
MineAgentViewModel.let {
|
||||||
|
it.refreshing = false
|
||||||
|
it.isLoading = false
|
||||||
|
it.hasNext = true
|
||||||
|
it.currentPage = 1
|
||||||
|
it.error = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置动态相关ViewModel
|
||||||
|
TimelineMomentViewModel.ResetModel()
|
||||||
|
DynamicViewModel.ResetModel()
|
||||||
|
HotMomentViewModel.ResetModel()
|
||||||
|
|
||||||
|
// 重置个人资料相关ViewModel
|
||||||
|
MyProfileViewModel.ResetModel()
|
||||||
|
|
||||||
|
// 重置搜索相关ViewModel
|
||||||
|
// DiscoverViewModel的属性是私有的,无法直接访问,通过其他方式清理
|
||||||
|
|
||||||
|
SearchViewModel.ResetModel()
|
||||||
|
|
||||||
|
// 重置消息相关ViewModel
|
||||||
|
MessageListViewModel.ResetModel()
|
||||||
|
|
||||||
|
// 重置通知相关ViewModel
|
||||||
|
LikeNoticeViewModel.ResetModel()
|
||||||
|
FavouriteNoticeViewModel.ResetModel()
|
||||||
|
FollowerNoticeViewModel.ResetModel()
|
||||||
|
|
||||||
|
// 重置收藏相关ViewModel
|
||||||
|
FavouriteListViewModel.ResetModel()
|
||||||
|
|
||||||
|
// 重置发布相关ViewModel
|
||||||
|
NewPostViewModel.asNewPost()
|
||||||
|
|
||||||
|
// 重置图片查看器ViewModel
|
||||||
|
ImageViewerViewModel.let {
|
||||||
|
it.imageList.clear()
|
||||||
|
it.initialIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理EventBus注册
|
||||||
|
*/
|
||||||
|
private fun cleanupEventBus() {
|
||||||
|
try {
|
||||||
|
// 取消所有ViewModel的EventBus注册
|
||||||
|
val eventBus = EventBus.getDefault()
|
||||||
|
|
||||||
|
// 检查并取消注册各种ViewModel
|
||||||
|
if (eventBus.isRegistered(TimelineMomentViewModel)) {
|
||||||
|
eventBus.unregister(TimelineMomentViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(DynamicViewModel)) {
|
||||||
|
eventBus.unregister(DynamicViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(HotMomentViewModel)) {
|
||||||
|
eventBus.unregister(HotMomentViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(MyProfileViewModel)) {
|
||||||
|
eventBus.unregister(MyProfileViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(DiscoverViewModel)) {
|
||||||
|
eventBus.unregister(DiscoverViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(SearchViewModel)) {
|
||||||
|
eventBus.unregister(SearchViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(MessageListViewModel)) {
|
||||||
|
eventBus.unregister(MessageListViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(LikeNoticeViewModel)) {
|
||||||
|
eventBus.unregister(LikeNoticeViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(FavouriteListViewModel)) {
|
||||||
|
eventBus.unregister(FavouriteListViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(FavouriteNoticeViewModel)) {
|
||||||
|
eventBus.unregister(FavouriteNoticeViewModel)
|
||||||
|
}
|
||||||
|
if (eventBus.isRegistered(FollowerNoticeViewModel)) {
|
||||||
|
eventBus.unregister(FollowerNoticeViewModel)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// EventBus清理失败不影响其他清理
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理服务
|
||||||
|
*/
|
||||||
|
private fun cleanupServices(context: Context) {
|
||||||
|
try {
|
||||||
|
// 停止TRTC服务
|
||||||
|
// val trtcService = Intent(context, TrtcService::class.java)
|
||||||
|
// context.stopService(trtcService)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// 服务停止失败不影响其他清理
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理缓存和临时数据
|
||||||
|
*/
|
||||||
|
private fun cleanupCacheAndTempData() {
|
||||||
|
try {
|
||||||
|
// 清理图片缓存
|
||||||
|
// 这里可以添加图片缓存清理逻辑
|
||||||
|
|
||||||
|
// 清理临时文件
|
||||||
|
// 这里可以添加临时文件清理逻辑
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// 缓存清理失败不影响其他清理
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置应用状态
|
||||||
|
*/
|
||||||
|
private fun resetAppState() {
|
||||||
|
try {
|
||||||
|
// 重置用户ID
|
||||||
|
AppState.UserId = null
|
||||||
|
|
||||||
|
// 重置其他应用状态
|
||||||
|
// 这里可以添加其他应用状态的重置逻辑
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// 状态重置失败不影响其他清理
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理特定页面的资源
|
||||||
|
* @param pageType 页面类型
|
||||||
|
*/
|
||||||
|
fun cleanupPageResources(pageType: String) {
|
||||||
|
when (pageType) {
|
||||||
|
"ai" -> {
|
||||||
|
// AgentViewModel的属性是私有的,无法直接访问
|
||||||
|
HotAgentViewModel.let {
|
||||||
|
it.agentList = emptyList()
|
||||||
|
it.refreshing = false
|
||||||
|
it.isLoading = false
|
||||||
|
it.hasNext = true
|
||||||
|
it.currentPage = 1
|
||||||
|
it.error = null
|
||||||
|
it.clearPreloadedImages()
|
||||||
|
}
|
||||||
|
MineAgentViewModel.let {
|
||||||
|
it.refreshing = false
|
||||||
|
it.isLoading = false
|
||||||
|
it.hasNext = true
|
||||||
|
it.currentPage = 1
|
||||||
|
it.error = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"moment" -> {
|
||||||
|
TimelineMomentViewModel.ResetModel()
|
||||||
|
DynamicViewModel.ResetModel()
|
||||||
|
HotMomentViewModel.ResetModel()
|
||||||
|
}
|
||||||
|
"profile" -> {
|
||||||
|
MyProfileViewModel.ResetModel()
|
||||||
|
}
|
||||||
|
"search" -> {
|
||||||
|
// DiscoverViewModel的属性是私有的,无法直接访问
|
||||||
|
SearchViewModel.ResetModel()
|
||||||
|
}
|
||||||
|
"message" -> {
|
||||||
|
MessageListViewModel.ResetModel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user