manager: Fixed flickering on activity refresh using a clever method.

- Add Activity lifecycle callback and method to refresh current Activity
This commit is contained in:
ShirkNeko
2025-06-03 01:43:31 +08:00
parent 1d34ea4995
commit 07c9cce4b9
3 changed files with 166 additions and 88 deletions

View File

@@ -1,11 +1,14 @@
package com.sukisu.ultra package com.sukisu.ultra
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityOptions
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.os.Build import android.os.Build
import android.os.Bundle
import coil.Coil import coil.Coil
import coil.ImageLoader import coil.ImageLoader
import com.dergoogler.mmrl.platform.Platform import com.dergoogler.mmrl.platform.Platform
@@ -14,9 +17,31 @@ import me.zhanghai.android.appiconloader.coil.AppIconKeyer
import java.io.File import java.io.File
import java.util.Locale import java.util.Locale
@SuppressLint("StaticFieldLeak")
lateinit var ksuApp: KernelSUApplication lateinit var ksuApp: KernelSUApplication
class KernelSUApplication : Application() { class KernelSUApplication : Application() {
private var currentActivity: Activity? = null
private val activityLifecycleCallbacks = object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
currentActivity = activity
}
override fun onActivityStarted(activity: Activity) {
currentActivity = activity
}
override fun onActivityResumed(activity: Activity) {
currentActivity = activity
}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
if (currentActivity == activity) {
currentActivity = null
}
}
}
override fun attachBaseContext(base: Context) { override fun attachBaseContext(base: Context) {
val prefs = base.getSharedPreferences("settings", MODE_PRIVATE) val prefs = base.getSharedPreferences("settings", MODE_PRIVATE)
@@ -62,6 +87,9 @@ class KernelSUApplication : Application() {
super.onCreate() super.onCreate()
ksuApp = this ksuApp = this
// 注册Activity生命周期回调
registerActivityLifecycleCallbacks(activityLifecycleCallbacks)
Platform.setHiddenApiExemptions() Platform.setHiddenApiExemptions()
val context = this val context = this
@@ -107,4 +135,17 @@ class KernelSUApplication : Application() {
} }
} }
} }
// 添加刷新当前Activity的方法
fun refreshCurrentActivity() {
currentActivity?.let { activity ->
val intent = activity.intent
activity.finish()
val options = ActivityOptions.makeCustomAnimation(
activity, android.R.anim.fade_in, android.R.anim.fade_out
)
activity.startActivity(intent, options.toBundle())
}
}
} }

View File

@@ -44,12 +44,16 @@ class MainActivity : ComponentActivity() {
private lateinit var themeChangeObserver: ThemeChangeContentObserver private lateinit var themeChangeObserver: ThemeChangeContentObserver
// 添加标记避免重复初始化
private var isInitialized = false
override fun attachBaseContext(newBase: Context) { override fun attachBaseContext(newBase: Context) {
val context = LocaleUtils.applyLocale(newBase) val context = LocaleUtils.applyLocale(newBase)
super.attachBaseContext(context) super.attachBaseContext(context)
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
try {
// 确保应用正确的语言设置 // 确保应用正确的语言设置
LocaleUtils.applyLanguageSetting(this) LocaleUtils.applyLanguageSetting(this)
@@ -65,36 +69,11 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// 初始化 SuperUserViewModel // 使用标记控制初始化流程
superUserViewModel = SuperUserViewModel() if (!isInitialized) {
initializeViewModels()
lifecycleScope.launch { initializeData()
superUserViewModel.fetchAppList() isInitialized = true
}
// 初始化 HomeViewModel
homeViewModel = HomeViewModel()
// 预加载数据
lifecycleScope.launch {
homeViewModel.initializeData()
}
// 数据刷新协程
DataRefreshUtils.startDataRefreshCoroutine(lifecycleScope)
DataRefreshUtils.startSettingsMonitorCoroutine(lifecycleScope, this, settingsStateFlow)
// 初始化主题相关设置
ThemeUtils.initializeThemeSettings(this, settingsStateFlow)
// 设置主题变化监听器
themeChangeObserver = ThemeUtils.registerThemeChangeObserver(this)
val isManager = AppData.isManager(ksuApp.packageName)
if (isManager) {
install()
UltraToolInstall.tryToInstall()
} }
setContent { setContent {
@@ -104,11 +83,10 @@ class MainActivity : ComponentActivity() {
val currentDestination = navController.currentBackStackEntryAsState().value?.destination val currentDestination = navController.currentBackStackEntryAsState().value?.destination
val showBottomBar = when (currentDestination?.route) { val showBottomBar = when (currentDestination?.route) {
ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen ExecuteModuleActionScreenDestination.route -> false
else -> true else -> true
} }
// pre-init platform to faster start WebUI X activities
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
initPlatform() initPlatform()
} }
@@ -135,36 +113,101 @@ class MainActivity : ComponentActivity() {
} }
} }
} }
} catch (e: Exception) {
e.printStackTrace()
}
} }
override fun onPause() { private fun initializeViewModels() {
super.onPause() superUserViewModel = SuperUserViewModel()
ThemeUtils.onActivityPause(this) homeViewModel = HomeViewModel()
// 设置主题变化监听器
themeChangeObserver = ThemeUtils.registerThemeChangeObserver(this)
}
private fun initializeData() {
lifecycleScope.launch {
try {
superUserViewModel.fetchAppList()
} catch (e: Exception) {
e.printStackTrace()
}
}
lifecycleScope.launch {
try {
homeViewModel.initializeData()
} catch (e: Exception) {
e.printStackTrace()
}
}
// 数据刷新协程
DataRefreshUtils.startDataRefreshCoroutine(lifecycleScope)
DataRefreshUtils.startSettingsMonitorCoroutine(lifecycleScope, this, settingsStateFlow)
// 初始化主题相关设置
ThemeUtils.initializeThemeSettings(this, settingsStateFlow)
val isManager = AppData.isManager(ksuApp.packageName)
if (isManager) {
install()
UltraToolInstall.tryToInstall()
}
} }
override fun onResume() { override fun onResume() {
try {
super.onResume() super.onResume()
LocaleUtils.applyLanguageSetting(this) LocaleUtils.applyLanguageSetting(this)
ThemeUtils.onActivityResume() ThemeUtils.onActivityResume()
// 仅在需要时刷新数据
if (isInitialized) {
refreshData()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun refreshData() {
lifecycleScope.launch { lifecycleScope.launch {
try {
superUserViewModel.fetchAppList() superUserViewModel.fetchAppList()
}
lifecycleScope.launch {
homeViewModel.initializeData() homeViewModel.initializeData()
DataRefreshUtils.refreshData(lifecycleScope)
} catch (e: Exception) {
e.printStackTrace()
}
}
} }
DataRefreshUtils.refreshData(lifecycleScope) override fun onPause() {
try {
super.onPause()
ThemeUtils.onActivityPause(this)
} catch (e: Exception) {
e.printStackTrace()
}
} }
override fun onDestroy() { override fun onDestroy() {
try {
ThemeUtils.unregisterThemeChangeObserver(this, themeChangeObserver) ThemeUtils.unregisterThemeChangeObserver(this, themeChangeObserver)
super.onDestroy() super.onDestroy()
} catch (e: Exception) {
e.printStackTrace()
}
} }
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
try {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
LocaleUtils.applyLanguageSetting(this) LocaleUtils.applyLanguageSetting(this)
} catch (e: Exception) {
e.printStackTrace()
}
} }
} }

View File

@@ -90,6 +90,7 @@ import androidx.compose.material3.TextButton
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.sukisu.ultra.ksuApp
/** /**
* @author ShirkNeko * @author ShirkNeko
@@ -388,14 +389,7 @@ fun MoreSettingsScreen(
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
context.resources.updateConfiguration(config, context.resources.displayMetrics) context.resources.updateConfiguration(config, context.resources.displayMetrics)
} }
ksuApp.refreshCurrentActivity()
val intent = Intent(context, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
if (context is Activity) {
context.finish()
}
} }
} }