再次优化加载性能
This commit is contained in:
@@ -240,6 +240,7 @@ fun <T : Any> MyRefreshTableForCard(
|
||||
) {
|
||||
val state = rememberPullToRefreshState()
|
||||
val pagerSate = info.loadState.append
|
||||
val refreshState = info.loadState.refresh
|
||||
LaunchedEffect(pagerSate) {
|
||||
if (pagerSate is LoadState.NotLoading) {
|
||||
onFinishRefresh()
|
||||
@@ -272,6 +273,7 @@ fun <T : Any> MyRefreshTableForCard(
|
||||
}
|
||||
}
|
||||
) {
|
||||
Box(modifier = M.fillMaxSize()) {
|
||||
LazyVerticalGrid(
|
||||
modifier = M.fillMaxSize(),
|
||||
columns = GridCells.Fixed(columns),
|
||||
@@ -299,6 +301,12 @@ fun <T : Any> MyRefreshTableForCard(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (refreshState is LoadState.Loading && info.itemCount == 0) {
|
||||
Box(modifier = M.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
ListLoading()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -512,6 +520,7 @@ fun <T : Any> MyRefreshTable(
|
||||
val listState: LazyListState = rememberLazyListState()
|
||||
val state = rememberPullToRefreshState()
|
||||
val pagerSate = info.loadState.append
|
||||
val refreshState = info.loadState.refresh
|
||||
LaunchedEffect(pagerSate) {
|
||||
if (pagerSate is LoadState.NotLoading) {
|
||||
onFinishRefresh()
|
||||
@@ -553,6 +562,7 @@ fun <T : Any> MyRefreshTable(
|
||||
}
|
||||
}
|
||||
) {
|
||||
Box(modifier = M.fillMaxSize()) {
|
||||
var selectIndex by rememberSaveable { mutableStateOf(-1) }
|
||||
LazyColumn(state = listState) {
|
||||
items(
|
||||
@@ -648,6 +658,12 @@ fun <T : Any> MyRefreshTable(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (refreshState is LoadState.Loading && info.itemCount == 0) {
|
||||
Box(modifier = M.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
ListLoading()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,11 +54,12 @@ open class BaseViewModel : ViewModel() {
|
||||
onUI: (T) -> Unit,
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
val result = kotlin.runCatching {
|
||||
withContext(Dispatchers.IO) {
|
||||
if (showDialog) {
|
||||
Toasty.showLoadingDialog(loadingTips)
|
||||
}
|
||||
|
||||
val result = kotlin.runCatching {
|
||||
withContext(Dispatchers.IO) {
|
||||
onIO()
|
||||
}
|
||||
}
|
||||
@@ -67,7 +68,6 @@ open class BaseViewModel : ViewModel() {
|
||||
hideLoadingDialog()
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
result.onSuccess { data ->
|
||||
onUI(data)
|
||||
}.onFailure { exception ->
|
||||
@@ -96,7 +96,6 @@ open class BaseViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun <T> doInIoThread(
|
||||
|
||||
@@ -20,12 +20,13 @@ import androidx.navigation.compose.rememberNavController
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavHostController
|
||||
import com.bbitcn.f8.pad.M
|
||||
@@ -47,8 +48,8 @@ import com.bbitcn.f8.pad.ui.screen.mainFunc.UserScreen
|
||||
import com.bbitcn.f8.pad.ui.screen.view.Toasty
|
||||
import com.bbitcn.f8.pad.ui.viewmodel.UpdateViewModel
|
||||
import com.cyberecho.ui.screen.ChatDialog
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.xutils.db.annotation.Column
|
||||
|
||||
@Preview(showBackground = true, widthDp = 1280)
|
||||
@Composable
|
||||
@@ -74,9 +75,43 @@ fun MainScreen(
|
||||
}
|
||||
Box(modifier = M.fillMaxWidth(), contentAlignment = Alignment.BottomStart) {
|
||||
var selectedPage by rememberSaveable { mutableStateOf(0) }
|
||||
var contentPage by rememberSaveable { mutableStateOf(0) }
|
||||
var isSwitchingPage by remember { mutableStateOf(false) }
|
||||
val cachedPages = remember { mutableStateListOf<Int>() }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val menu by mainViewModel.menu.collectAsState()
|
||||
LaunchedEffect(menu, selectedPage) {
|
||||
if (menu.isEmpty()) {
|
||||
contentPage = 0
|
||||
isSwitchingPage = false
|
||||
cachedPages.clear()
|
||||
return@LaunchedEffect
|
||||
}
|
||||
|
||||
val safeSelectedPage = selectedPage.coerceIn(0, menu.lastIndex)
|
||||
if (safeSelectedPage != selectedPage) {
|
||||
selectedPage = safeSelectedPage
|
||||
return@LaunchedEffect
|
||||
}
|
||||
|
||||
cachedPages.removeAll { it !in menu.indices }
|
||||
if (cachedPages.isEmpty()) {
|
||||
cachedPages.add(safeSelectedPage)
|
||||
}
|
||||
|
||||
if (contentPage != safeSelectedPage && safeSelectedPage !in cachedPages) {
|
||||
isSwitchingPage = true
|
||||
withFrameNanos { }
|
||||
delay(180)
|
||||
cachedPages.add(safeSelectedPage)
|
||||
contentPage = safeSelectedPage
|
||||
isSwitchingPage = false
|
||||
} else if (contentPage != safeSelectedPage) {
|
||||
contentPage = safeSelectedPage
|
||||
isSwitchingPage = false
|
||||
}
|
||||
}
|
||||
Row(modifier = M.fillMaxWidth()) {
|
||||
NavigationRail(
|
||||
containerColor = MyColors.Black,
|
||||
@@ -99,37 +134,39 @@ fun MainScreen(
|
||||
)
|
||||
},
|
||||
selected = selectedPage == index,
|
||||
onClick = { selectedPage = index }
|
||||
onClick = {
|
||||
if (selectedPage != index) {
|
||||
selectedPage = index
|
||||
isSwitchingPage = index !in cachedPages
|
||||
if (index in cachedPages) {
|
||||
contentPage = index
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Box {
|
||||
var index = -1
|
||||
if (menu.isNotEmpty()) {
|
||||
index = menu[selectedPage].index
|
||||
}
|
||||
when (index) {
|
||||
-1 -> {
|
||||
Box(modifier = M.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text("正在加载菜单,如长时间未响应请点击重新加载")
|
||||
MyButton(text = "刷新菜单") {
|
||||
mainViewModel.refreshMenuPermission()
|
||||
Box(modifier = M.weight(1f).fillMaxSize()) {
|
||||
val selectedMenu = menu.getOrNull(selectedPage)
|
||||
if (isSwitchingPage && selectedMenu != null && selectedPage !in cachedPages) {
|
||||
MainPageLoading(selectedMenu.title)
|
||||
} else {
|
||||
cachedPages.forEach { page ->
|
||||
key(page) {
|
||||
val pageIndex = menu.getOrNull(page)?.index ?: -1
|
||||
MainPageHost(visible = page == contentPage) {
|
||||
MainPageContent(
|
||||
index = pageIndex,
|
||||
navController = navController,
|
||||
drawerViewModel = drawerViewModel,
|
||||
updateViewModel = updateViewModel,
|
||||
topInfoViewmodel = topInfoViewmodel,
|
||||
mainViewModel = mainViewModel
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0 -> HomeScreen(navController)
|
||||
1 -> UserScreen(navController)
|
||||
2 -> PurchaseScreen(navController, drawerViewModel = drawerViewModel)
|
||||
3 -> FundsScreen(navController, drawerViewModel = drawerViewModel)
|
||||
4 -> StatisticsScreen(drawerViewModel = drawerViewModel)
|
||||
5 -> DryCoonScreen(navController, drawerViewModel)
|
||||
6 -> SettingScreen(navController, updateViewModel = updateViewModel, topInfoViewmodel = topInfoViewmodel){
|
||||
mainViewModel.refreshMenuPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Column(
|
||||
@@ -208,3 +245,69 @@ fun MainScreen(
|
||||
val chatDialogData by mainViewModel.chatDialogData.collectAsState()
|
||||
ChatDialog(chatDialogData)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainPageLoading(title: String) {
|
||||
Box(modifier = M.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Text(
|
||||
text = "正在加载$title...",
|
||||
color = MyColors.Gray,
|
||||
fontSize = MaterialTheme.typography.bodyLarge.fontSize
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainPageHost(
|
||||
visible: Boolean,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = if (visible) {
|
||||
M
|
||||
.fillMaxSize()
|
||||
.alpha(1f)
|
||||
.zIndex(1f)
|
||||
} else {
|
||||
M
|
||||
.size(0.dp)
|
||||
.alpha(0f)
|
||||
.zIndex(0f)
|
||||
}
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainPageContent(
|
||||
index: Int,
|
||||
navController: NavHostController,
|
||||
drawerViewModel: DrawerViewModel,
|
||||
updateViewModel: UpdateViewModel,
|
||||
topInfoViewmodel: TopInfoViewModel,
|
||||
mainViewModel: MainViewModel
|
||||
) {
|
||||
when (index) {
|
||||
-1 -> {
|
||||
Box(modifier = M.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text("正在加载菜单,如长时间未响应请点击重新加载")
|
||||
MyButton(text = "刷新菜单") {
|
||||
mainViewModel.refreshMenuPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0 -> HomeScreen(navController)
|
||||
1 -> UserScreen(navController)
|
||||
2 -> PurchaseScreen(navController, drawerViewModel = drawerViewModel)
|
||||
3 -> FundsScreen(navController, drawerViewModel = drawerViewModel)
|
||||
4 -> StatisticsScreen(drawerViewModel = drawerViewModel)
|
||||
5 -> DryCoonScreen(navController, drawerViewModel)
|
||||
6 -> SettingScreen(navController, updateViewModel = updateViewModel, topInfoViewmodel = topInfoViewmodel) {
|
||||
mainViewModel.refreshMenuPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -45,6 +46,7 @@ import com.bbitcn.f8.pad.ui.screen.view.Toasty
|
||||
import com.bbitcn.f8.pad.ui.screen.view.common.DatePickerRange
|
||||
import com.bbitcn.f8.pad.ui.screen.view.drawer.DrawerViewModel
|
||||
import com.bbitcn.f8.pad.ui.theme.MyColors
|
||||
import kotlinx.coroutines.delay
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.LocalDate
|
||||
import java.util.Locale
|
||||
@@ -69,8 +71,18 @@ fun StatisticsScreen(
|
||||
val ticketMoreDialogData by remember { mutableStateOf(TicketMoreDialogData()) }
|
||||
var curType by remember { mutableStateOf(StatisticsResponse.Data()) }
|
||||
var queryInput by rememberSaveable { mutableStateOf("") }
|
||||
var queryInputInitialized by rememberSaveable { mutableStateOf(false) }
|
||||
val pager = statisticsViewModel.statisticsPager.collectAsLazyPagingItems()
|
||||
val dateRangeSelectDialogData by statisticsViewModel.dateRangeSelectDialogData.collectAsState()
|
||||
LaunchedEffect(queryInput) {
|
||||
if (!queryInputInitialized) {
|
||||
queryInputInitialized = true
|
||||
return@LaunchedEffect
|
||||
}
|
||||
delay(350)
|
||||
statisticsViewModel.updateParamsLike(queryInput)
|
||||
pager.refresh()
|
||||
}
|
||||
MainFuncFrame {
|
||||
MyCard(colors = MyColors.LightLightBlueGreen) {
|
||||
Row(
|
||||
@@ -79,10 +91,12 @@ fun StatisticsScreen(
|
||||
.padding(10.dp)
|
||||
) {
|
||||
StatisticsLeft(modifier = M.weight(2f), statisticsViewModel, curType, pager) {
|
||||
if (curType.sgtypesysid != it.sgtypesysid) {
|
||||
curType = it
|
||||
statisticsViewModel.updateParamsCocoonType(it.sgtypesysid)
|
||||
pager.refresh()
|
||||
}
|
||||
}
|
||||
StatisticsMain(
|
||||
modifier = M.weight(8f),
|
||||
statisticsViewModel,
|
||||
@@ -90,8 +104,6 @@ fun StatisticsScreen(
|
||||
queryInput,
|
||||
{
|
||||
queryInput = it
|
||||
statisticsViewModel.updateParamsLike(queryInput)
|
||||
pager.refresh()
|
||||
},
|
||||
curType.name,
|
||||
{
|
||||
@@ -119,6 +131,7 @@ fun StatisticsLeft(
|
||||
) {
|
||||
val daysInfo by statisticsViewModel.daysInfo.collectAsState()
|
||||
val statistics by statisticsViewModel.statistics.collectAsState()
|
||||
val dayFormat = remember { SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) }
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
@@ -131,11 +144,13 @@ fun StatisticsLeft(
|
||||
statisticsViewModel.calDate = it
|
||||
statisticsViewModel.getDaysInfo(it.year.toString(), it.monthValue.toString())
|
||||
}) { start, end ->
|
||||
val dateStart = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(start)
|
||||
val dateEnd = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(end)
|
||||
val dateStart = dayFormat.parse(start)
|
||||
val dateEnd = dayFormat.parse(end)
|
||||
if (dateStart != null && dateEnd != null) {
|
||||
statisticsViewModel.refreshDateRange(dateStart to dateEnd)
|
||||
pager.refresh()
|
||||
}
|
||||
}
|
||||
val dateRange by statisticsViewModel.dateRange.collectAsState()
|
||||
DateRangePickTextFiled(M.fillMaxWidth(), dateRange = dateRange) {
|
||||
statisticsViewModel.showDateRangeSelectDialog {
|
||||
|
||||
@@ -67,6 +67,7 @@ fun DatePickerRange(
|
||||
// 处理拖动选择日期范围
|
||||
var selectedStartDay by remember { mutableStateOf(-1) }
|
||||
var selectedEndDay by remember { mutableStateOf(-1) }
|
||||
val importantDaySet = remember(importantDateInfoList) { importantDateInfoList.toSet() }
|
||||
|
||||
val onClickChangeDate: (date: LocalDate) -> Unit = { date ->
|
||||
currentDate = date
|
||||
@@ -158,7 +159,7 @@ fun DatePickerRange(
|
||||
items(currentDate.lengthOfMonth() + 1) { day ->
|
||||
CalendarDay(
|
||||
day,
|
||||
importantDateInfoList.contains(day),
|
||||
importantDaySet.contains(day),
|
||||
rangeType = if (day == selectedStartDay)
|
||||
if (selectedEndDay == -1
|
||||
|| selectedEndDay == selectedStartDay
|
||||
|
||||
Reference in New Issue
Block a user