1、减少io操作使用冷流方式一次性完成通知消息的处理
This commit is contained in:
shenzuqiang 2026-03-12 10:17:23 +08:00
parent db36d63082
commit 8c21b3127e
8 changed files with 68 additions and 124 deletions

View File

@ -111,34 +111,33 @@ class MainActivity : ComponentActivity(), LoadingCallback {
generalViewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(application))[GeneralViewModel::class.java]
val globalStateManager = remember { GlobalStateManager(context) }
val updateAppNotify by globalStateManager.globalUpdateNotifyFlow().collectAsState(initial = false)
val updateUserConfigNotify by globalStateManager.globalUserConfigNotifyFlow().collectAsState(initial = false)
val updateUniUpdateNotify by globalStateManager.globalUniUpdateNotifyFlow().collectAsState(initial = false)
// val updateGlobalLoadingNotify by globalStateManager.isGlobalLoadingFlow().collectAsState(initial = false)
//重置状态信息(防止异常退出导致状态失效)
LaunchedEffect(Unit) {
globalStateManager.apply {
storeGlobalUpdateNotify(false)
storeGlobalUserConfigNotify(false)
storeGlobalUniUpdateNotify(false)
// storeGlobalLoading(false)
}
}
val isGlobalLoading by generalViewModel.isLoading.collectAsState()
// 下载小程序资源(在跳转指定页面时,未下载资源需要提示)
var showUniDownloadDialog by remember { mutableStateOf(false) }
var downloadUniEntity by remember { mutableStateOf<UniVersionEntity?>(null) }
// 软件更新提示
var showUpdateDialog by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
GeneralViewModel.GlobalEventBus.events.collect { event ->
when (event) {
// 软件更新提示
is GeneralViewModel.GlobalEvent.ShowAppUpdateNotify -> {
showUpdateDialog = true
}
// 小程序资源下载提示
is GeneralViewModel.GlobalEvent.ShowUniDownloadNotify -> {
downloadUniEntity = event.entity
showUniDownloadDialog = true
}
is GeneralViewModel.GlobalEvent.ShowAppUpdateNotify -> {
// 处理 App 更新弹窗逻辑
}
// ... 处理其他事件
else -> {}
}
@ -190,16 +189,6 @@ class MainActivity : ComponentActivity(), LoadingCallback {
}
}
//还原全局用户配置通知
LaunchedEffect(updateUserConfigNotify) {
delay(300)
if(updateUserConfigNotify == true){
coroutineScope.launch {
globalStateManager.storeGlobalUserConfigNotify(false)
}
}
}
//提示下载小程序资源(在跳转指定页面时,未下载资源需要提示)
val progressWGTToPageState = remember { mutableFloatStateOf(0f) }
LaunchedEffect(showUniDownloadDialog) {
@ -353,54 +342,49 @@ class MainActivity : ComponentActivity(), LoadingCallback {
//App更新提示
val isStartDownload = mutableStateOf(false)
val progressState = mutableFloatStateOf(0f)
if(updateAppNotify == true){
UpdateDialog(
title = PreferenceUtil.getUserConfig()?.config?.versionEntity?.title?:"新版本,更新提示",
newVersion = "V${PreferenceUtil.getUserConfig()?.config?.versionEntity?.version}",
desc = PreferenceUtil.getUserConfig()?.config?.versionEntity?.description?:"",
url = PreferenceUtil.getUserConfig()?.config?.versionEntity?.url?:"",
scope = coroutineScope,
isForce = PreferenceUtil.getUserConfig()?.config?.versionEntity?.force?:false,
isStartDown = isStartDownload,
downProgress = progressState
){ state, isCancel, url ->
if(isCancel) {
coroutineScope.launch {
globalStateManager.storeGlobalUpdateNotify(state)
if(showUpdateDialog){
val versionEntity = PreferenceUtil.getUserConfig()?.config?.versionEntity
versionEntity?.let{ versionEntity->
UpdateDialog(
title = versionEntity.title,
newVersion = "V${versionEntity.version}",
desc = versionEntity.description,
url = versionEntity.url,
isForce = versionEntity.force,
isStartDown = isStartDownload,
downProgress = progressState
){ state, isCancel, url ->
if(isCancel) {
showUpdateDialog = false
}
}
if(!isCancel){
isStartDownload.value = true
UpdateUtils.download(
scope = coroutineScope,
url = url,
filePath = FileUtils.instance?.cacheDownLoadDir?.absolutePath?:"",
fileName = AppUpdate.getFileNameFromUrl(url),
onProgress = {progress->
progressState.floatValue = progress.toFloat()/100f
},
onFinish = {isSuccess, filePath ->
if(isSuccess){
filePath?.let {
UpdateUtils.install(context,it)
}
if(PreferenceUtil.getUserConfig()?.config?.versionEntity?.force == false) {
coroutineScope.launch {
globalStateManager.storeGlobalUpdateNotify(
state
)
if(!isCancel){
isStartDownload.value = true
UpdateUtils.download(
scope = coroutineScope,
url = url,
filePath = FileUtils.instance?.cacheDownLoadDir?.absolutePath?:"",
fileName = AppUpdate.getFileNameFromUrl(url),
onProgress = {progress->
progressState.floatValue = progress.toFloat()/100f
},
onFinish = {isSuccess, filePath ->
if(isSuccess){
filePath?.let {
UpdateUtils.install(context,it)
}
if(!versionEntity.force) {
showUpdateDialog = state
}
}
}
}
)
)
}
}
}
}
//全局加载提示
if(isGlobalLoading){
// if (updateGlobalLoadingNotify == true) {
Log.i("HomeScreen","isStartOn--->${System.currentTimeMillis()}")
Box(
modifier = Modifier
@ -435,7 +419,6 @@ class MainActivity : ComponentActivity(), LoadingCallback {
override fun showLoading() {
lifecycleScope.launch {
// GlobalStateManager(this@MainActivity).storeGlobalLoading(true)
generalViewModel.setLoading(true)
}
@ -444,7 +427,6 @@ class MainActivity : ComponentActivity(), LoadingCallback {
override fun hideLoading() {
lifecycleScope.launch {
delay(3000L)
// GlobalStateManager(this@MainActivity).storeGlobalLoading(false)
generalViewModel.setLoading(false)
}
}

View File

@ -178,6 +178,7 @@ fun MainScreen(generalViewModel: GeneralViewModel, loginViewModel: LoginViewMode
composable(ScreenRoute.Home.route) {
HomeScreen(
navController = navController,
loginViewModel = loginViewModel,
generalViewModel = generalViewModel,
loadingCallback = LocalContext.current as? LoadingCallback
)
@ -185,6 +186,7 @@ fun MainScreen(generalViewModel: GeneralViewModel, loginViewModel: LoginViewMode
composable(ScreenRoute.Mine.route) {
MineScreen(
navController = navController,
loginViewModel = loginViewModel,
generalViewModel = generalViewModel
)
}

View File

@ -53,7 +53,6 @@ fun UpdateDialog(
newVersion: String = "V1.0.0",
desc: String = "修复了一些问题,新增了一些功能",
url: String,
scope: CoroutineScope,
isForce: Boolean = false,
isStartDown: MutableState<Boolean>,
downProgress: MutableState<Float>,

View File

@ -61,6 +61,7 @@ import com.img.rabbit.route.ScreenRoute
import com.img.rabbit.utils.UniAppUtils
import com.img.rabbit.utils.UniMpUpdate
import com.img.rabbit.viewmodel.GeneralViewModel
import com.img.rabbit.viewmodel.LoginViewModel
import com.img.rabbit.viewmodel.ReportViewModel
import io.dcloud.feature.sdk.DCUniMPSDK
import kotlinx.coroutines.CoroutineScope
@ -71,6 +72,7 @@ import org.json.JSONObject
@Composable
fun HomeScreen(
navController: NavHostController,
loginViewModel: LoginViewModel,
generalViewModel: GeneralViewModel,
reportViewModel: ReportViewModel = viewModel(),
loadingCallback: LoadingCallback?
@ -86,8 +88,6 @@ fun HomeScreen(
// 只有当当前路由处于首页 Tab 之一时,才激活 BackHandler
var lastClickTime by remember { mutableLongStateOf(0L) }
val updateUserConfigNotify by GlobalStateManager(context).globalUserConfigNotifyFlow().collectAsState(initial = false)
BackHandler(enabled = (currentRoute == ScreenRoute.Home.route)) {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime > 2000) {
@ -113,8 +113,8 @@ fun HomeScreen(
var homeIconConfig by remember { mutableStateOf(PreferenceUtil.getUserConfig()?.config?.homeIconEntity) }
var uniVersionConfig by remember { mutableStateOf(PreferenceUtil.getUserConfig()?.config?.uniVersionEntity) }
LaunchedEffect(updateUserConfigNotify) {
if(updateUserConfigNotify == true){
LaunchedEffect(loginViewModel.userConfigResult.value) {
if(loginViewModel.userConfigResult.value != null){
homeIconConfig = PreferenceUtil.getUserConfig()?.config?.homeIconEntity
uniVersionConfig = PreferenceUtil.getUserConfig()?.config?.uniVersionEntity
}
@ -1490,7 +1490,7 @@ fun HomeScreen(
@Preview(showBackground = true)
@Composable
private fun PreviewHomeScreen() {
HomeScreen(navController = rememberNavController(), generalViewModel = viewModel(), reportViewModel = viewModel(), object: LoadingCallback{
HomeScreen(navController = rememberNavController(), loginViewModel = viewModel(), generalViewModel = viewModel(), reportViewModel = viewModel(), object: LoadingCallback{
override fun showLoading() {
}

View File

@ -21,7 +21,7 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
@ -48,7 +48,6 @@ import coil3.compose.AsyncImage
import com.img.rabbit.BuildConfig
import com.img.rabbit.R
import com.img.rabbit.components.CenterToast
import com.img.rabbit.provider.storage.GlobalStateManager
import com.img.rabbit.provider.storage.PreferenceUtil
import com.img.rabbit.route.ScreenRoute
import com.img.rabbit.utils.AppUpdate
@ -63,15 +62,14 @@ import kotlinx.coroutines.launch
fun MineScreen(
navController: NavHostController,
viewModel: MineViewModel = viewModel(),
loginViewModel: LoginViewModel,
generalViewModel: GeneralViewModel,
) {
val TAG = "Rabbit_Mine"
val context = LocalContext.current
val scope = rememberCoroutineScope()
var updateUserConfigNotify by mutableStateOf(GlobalStateManager(context).globalUserConfigNotifyFlow().collectAsState(initial = false))
//用户数据
var userInfo by remember { mutableStateOf(PreferenceUtil.getUserInfo()) }
// 获取当前路由状态
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
@ -88,9 +86,9 @@ fun MineScreen(
}
}
//刷新用户信息
if(updateUserConfigNotify.value == true){
scope.launch {
LaunchedEffect(loginViewModel.userConfigResult.value) {
if(loginViewModel.userConfigResult.value != null){
// 等待200ms确保用户配置已经刷新
delay(200)
userInfo = PreferenceUtil.getUserInfo()
@ -451,7 +449,8 @@ fun MineScreen(
//提示执行更新
//startUpdate(result, fragment)
scope.launch {
GlobalStateManager(context).storeGlobalUpdateNotify(true)
GeneralViewModel.GlobalEventBus.emit(
GeneralViewModel.GlobalEvent.ShowAppUpdateNotify)
}
} else {
CenterToast.show(tips)
@ -568,5 +567,5 @@ fun MineScreen(
@Preview(showBackground = true)
@Composable
private fun PreviewMineScreen(){
MineScreen(navController = rememberNavController(), generalViewModel = viewModel())
MineScreen(navController = rememberNavController(), loginViewModel = viewModel(), generalViewModel = viewModel())
}

View File

@ -15,37 +15,9 @@ class GlobalStateManager(
private val context: Context
) {
companion object {
private val GLOBAL_LOADING = booleanPreferencesKey("global_loading")
private val GLOBAL_UPDATE_NOTIFY = booleanPreferencesKey("global_update_notify")
private val GLOBAL_UNI_UPDATE_NOTIFY = booleanPreferencesKey("global_uni_update_notify")
private val GLOBAL_UNI_DOWNLOAD_NOTIFY = booleanPreferencesKey("global_uni_download_notify")
private val GLOBAL_USER_CONFIG_NOTIFY = booleanPreferencesKey("global_user_config_notify")
}
// suspend fun storeGlobalLoading(value: Boolean) {
// context.storeData.edit { preferences ->
// preferences[GLOBAL_LOADING] = value
// }
// }
// fun isGlobalLoadingFlow(): Flow<Boolean?> {
// return context.storeData.data.map {
// preferences ->
// preferences[GLOBAL_LOADING]
// }
// }
suspend fun storeGlobalUpdateNotify(value: Boolean) {
context.storeData.edit { preferences ->
preferences[GLOBAL_UPDATE_NOTIFY] = value
}
}
fun globalUpdateNotifyFlow(): Flow<Boolean?> {
return context.storeData.data.map {
preferences ->
preferences[GLOBAL_UPDATE_NOTIFY]
}
}
suspend fun storeGlobalUniUpdateNotify(value: Boolean) {
context.storeData.edit { preferences ->
@ -59,19 +31,4 @@ class GlobalStateManager(
}
}
suspend fun storeGlobalUserConfigNotify(value: Boolean) {
context.storeData.edit { preferences ->
preferences[GLOBAL_USER_CONFIG_NOTIFY] = value
}
}
fun globalUserConfigNotifyFlow(): Flow<Boolean?> {
return context.storeData.data.map {
preferences ->
preferences[GLOBAL_USER_CONFIG_NOTIFY]
}
}
}

View File

@ -16,6 +16,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.img.rabbit.bean.response.UniVersionEntity
import com.img.rabbit.bean.response.VersionEntity
import com.img.rabbit.config.Constants
import com.img.rabbit.provider.api.ApiManager
import com.img.rabbit.provider.storage.PreferenceUtil
@ -43,9 +44,9 @@ class GeneralViewModel: BaseViewModel(){
// 可以定义一个事件密封类,方便扩展
sealed class GlobalEvent {
object ShowAppUpdateNotify : GlobalEvent()
data class ShowUniDownloadNotify(val entity: UniVersionEntity) : GlobalEvent()
data class ShowUniUpdateNotify(val entity: UniVersionEntity) : GlobalEvent()
object ShowAppUpdateNotify : GlobalEvent()
}
object GlobalEventBus {

View File

@ -108,17 +108,21 @@ class LoginViewModel : BaseViewModel() {
userConfigResult.value = response
if(isInitConfig){
AppUpdate.checkUpdate(response.data.config?.versionEntity) { isUpdate, isForce, _ ->
if(isUpdate && isForce){
//强制更新
val versionEntity = response.data.config?.versionEntity
AppUpdate.checkUpdate(versionEntity) { isUpdate, _, _ ->
if(isUpdate){
// 有更新,提示更新
viewModelScope.launch{
applicationContext?.let { GlobalStateManager(it) }?.storeGlobalUpdateNotify(true)
versionEntity?.let {
GeneralViewModel.GlobalEventBus.emit(
GeneralViewModel.GlobalEvent.ShowAppUpdateNotify)
}
}
}
}
}
//以下是刷新状态
applicationContext?.let { GlobalStateManager(it) }?.storeGlobalUserConfigNotify(true)
// applicationContext?.let { GlobalStateManager(it) }?.storeGlobalUserConfigNotify(true)
}else{
Log.w("LoginViewModel", "获取配置失败: code=${response.code}, message=${response.message}")
}