Manager: optimizing Home's data caching logic

This commit is contained in:
ShirkNeko
2025-05-31 20:26:23 +08:00
parent 8bf9cd0bee
commit a030a026b1
4 changed files with 62 additions and 66 deletions

View File

@@ -108,6 +108,7 @@ android {
} }
dependencies { dependencies {
implementation(libs.gson)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.navigation.compose) implementation(libs.androidx.navigation.compose)

View File

@@ -361,8 +361,8 @@ private fun StatusCard(
val workingModeText = when { val workingModeText = when {
systemStatus.lkmMode == true -> "LKM" systemStatus.lkmMode == true -> "LKM"
systemStatus.lkmMode == null && systemStatus.kernelVersion.isGKI1() -> "GKI1.0" systemStatus.lkmMode == null && systemStatus.kernelVersion.isGKI1() -> "GKI-1.0"
systemStatus.lkmMode == false || systemStatus.kernelVersion.isGKI() -> "GKI2.0" systemStatus.lkmMode == false || systemStatus.kernelVersion.isGKI() -> "GKI-2.0"
else -> "N-GKI" else -> "N-GKI"
} }
@@ -775,7 +775,7 @@ private fun InfoCard(
InfoCardItem( InfoCardItem(
stringResource(R.string.home_manager_version), stringResource(R.string.home_manager_version),
"${systemInfo.managerVersion.first} (${systemInfo.managerVersion.second})", "${systemInfo.managerVersion.first} (${systemInfo.managerVersion.second.toInt()})",
icon = Icons.Default.SettingsSuggest, icon = Icons.Default.SettingsSuggest,
) )

View File

@@ -11,34 +11,28 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.dergoogler.mmrl.platform.Platform.Companion.context
import com.google.gson.Gson
import com.sukisu.ultra.KernelVersion import com.sukisu.ultra.KernelVersion
import com.sukisu.ultra.Natives import com.sukisu.ultra.Natives
import com.sukisu.ultra.getKernelVersion import com.sukisu.ultra.getKernelVersion
import com.sukisu.ultra.ksuApp import com.sukisu.ultra.ksuApp
import com.sukisu.ultra.ui.util.checkNewVersion import com.sukisu.ultra.ui.util.*
import com.sukisu.ultra.ui.util.getKpmModuleCount
import com.sukisu.ultra.ui.util.getKpmVersion
import com.sukisu.ultra.ui.util.getModuleCount
import com.sukisu.ultra.ui.util.getSELinuxStatus
import com.sukisu.ultra.ui.util.getSuSFS
import com.sukisu.ultra.ui.util.getSuSFSFeatures
import com.sukisu.ultra.ui.util.getSuSFSVariant
import com.sukisu.ultra.ui.util.getSuSFSVersion
import com.sukisu.ultra.ui.util.getSuperuserCount
import com.sukisu.ultra.ui.util.module.LatestVersionInfo import com.sukisu.ultra.ui.util.module.LatestVersionInfo
import com.sukisu.ultra.ui.util.rootAvailable
import com.sukisu.ultra.ui.util.susfsSUS_SU_Mode
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import com.topjohnwu.superuser.internal.Utils.context import androidx.core.content.edit
class HomeViewModel : ViewModel() { class HomeViewModel : ViewModel() {
companion object { companion object {
private const val TAG = "HomeViewModel" private const val TAG = "HomeViewModel"
private val systemStatusCache = mutableMapOf<String, SystemStatus>() private const val CACHE_DURATION = 12 * 60 * 60 * 1000L
private val systemInfoCache = mutableMapOf<String, SystemInfo>() private const val PREFS_NAME = "home_cache"
private val versionInfoCache = mutableMapOf<String, LatestVersionInfo>() private const val KEY_SYSTEM_STATUS = "system_status"
private const val KEY_SYSTEM_INFO = "system_info"
private const val KEY_VERSION_INFO = "version_info"
private const val KEY_LAST_UPDATE = "last_update_time"
} }
// 系统状态 // 系统状态
@@ -70,23 +64,21 @@ class HomeViewModel : ViewModel() {
val kpmModuleCount: Int = 0 val kpmModuleCount: Int = 0
) )
// UI状态 private val gson = Gson()
private val prefs by lazy { ksuApp.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) }
var isRefreshing by mutableStateOf(false) var isRefreshing by mutableStateOf(false)
private set private set
// 系统状态信息
var systemStatus by mutableStateOf(SystemStatus()) var systemStatus by mutableStateOf(SystemStatus())
private set private set
// 系统详细信息
var systemInfo by mutableStateOf(SystemInfo()) var systemInfo by mutableStateOf(SystemInfo())
private set private set
// 更新信息
var latestVersionInfo by mutableStateOf(LatestVersionInfo()) var latestVersionInfo by mutableStateOf(LatestVersionInfo())
private set private set
// 用户设置
var isSimpleMode by mutableStateOf(false) var isSimpleMode by mutableStateOf(false)
private set private set
var isHideVersion by mutableStateOf(false) var isHideVersion by mutableStateOf(false)
@@ -100,7 +92,6 @@ class HomeViewModel : ViewModel() {
var showKpmInfo by mutableStateOf(true) var showKpmInfo by mutableStateOf(true)
private set private set
// 加载用户设置
fun loadUserSettings(context: Context) { fun loadUserSettings(context: Context) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
@@ -113,27 +104,45 @@ class HomeViewModel : ViewModel() {
} }
} }
// 初始化数据
fun initializeData() { fun initializeData() {
viewModelScope.launch { viewModelScope.launch {
val cachedStatus = systemStatusCache["status"] val currentTime = System.currentTimeMillis()
val cachedInfo = systemInfoCache["info"] val lastUpdateTime = prefs.getLong(KEY_LAST_UPDATE, 0)
val shouldRefresh = currentTime - lastUpdateTime > CACHE_DURATION
if (cachedStatus != null) { if (!shouldRefresh) {
systemStatus = cachedStatus loadCachedData()
} else { } else {
fetchSystemStatus() fetchAndSaveData()
} }
}
if (cachedInfo != null) { }
systemInfo = cachedInfo
} else { private fun loadCachedData() {
fetchSystemInfo() prefs.getString(KEY_SYSTEM_STATUS, null)?.let {
systemStatus = gson.fromJson(it, SystemStatus::class.java)
}
prefs.getString(KEY_SYSTEM_INFO, null)?.let {
systemInfo = gson.fromJson(it, SystemInfo::class.java)
}
prefs.getString(KEY_VERSION_INFO, null)?.let {
latestVersionInfo = gson.fromJson(it, LatestVersionInfo::class.java)
}
}
private suspend fun fetchAndSaveData() {
fetchSystemStatus()
fetchSystemInfo()
withContext(Dispatchers.IO) {
prefs.edit {
putString(KEY_SYSTEM_STATUS, gson.toJson(systemStatus))
putString(KEY_SYSTEM_INFO, gson.toJson(systemInfo))
putString(KEY_VERSION_INFO, gson.toJson(latestVersionInfo))
putLong(KEY_LAST_UPDATE, System.currentTimeMillis())
} }
} }
} }
// 检查更新
fun checkForUpdates(context: Context) { fun checkForUpdates(context: Context) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
@@ -141,18 +150,17 @@ class HomeViewModel : ViewModel() {
.getBoolean("check_update", true) .getBoolean("check_update", true)
if (checkUpdate) { if (checkUpdate) {
val cachedVersion = versionInfoCache["version"] val currentTime = System.currentTimeMillis()
val lastUpdateTime = prefs.getLong(KEY_LAST_UPDATE, 0)
val shouldRefresh = currentTime - lastUpdateTime > CACHE_DURATION
if (cachedVersion != null) { if (shouldRefresh) {
latestVersionInfo = cachedVersion val start = SystemClock.elapsedRealtime()
return@launch val newVersionInfo = checkNewVersion()
latestVersionInfo = newVersionInfo
prefs.edit { putString(KEY_VERSION_INFO, gson.toJson(newVersionInfo)) }
Log.i(TAG, "Update check completed in ${SystemClock.elapsedRealtime() - start}ms")
} }
val start = SystemClock.elapsedRealtime()
val newVersionInfo = checkNewVersion()
latestVersionInfo = newVersionInfo
versionInfoCache["version"] = newVersionInfo
Log.i(TAG, "Update check completed in ${SystemClock.elapsedRealtime() - start}ms")
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error checking for updates", e) Log.e(TAG, "Error checking for updates", e)
@@ -160,16 +168,11 @@ class HomeViewModel : ViewModel() {
} }
} }
// 刷新所有数据
fun refreshAllData(context: Context) { fun refreshAllData(context: Context) {
isRefreshing = true isRefreshing = true
viewModelScope.launch { viewModelScope.launch {
try { try {
systemStatusCache.clear() fetchAndSaveData()
systemInfoCache.clear()
versionInfoCache.clear()
fetchSystemStatus()
fetchSystemInfo()
checkForUpdates(context) checkForUpdates(context)
} finally { } finally {
isRefreshing = false isRefreshing = false
@@ -177,7 +180,6 @@ class HomeViewModel : ViewModel() {
} }
} }
// 获取系统状态
private suspend fun fetchSystemStatus() { private suspend fun fetchSystemStatus() {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
try { try {
@@ -188,7 +190,7 @@ class HomeViewModel : ViewModel() {
if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null
} }
val newStatus = SystemStatus( systemStatus = SystemStatus(
isManager = isManager, isManager = isManager,
ksuVersion = ksuVersion, ksuVersion = ksuVersion,
lkmMode = lkmMode, lkmMode = lkmMode,
@@ -197,16 +199,12 @@ class HomeViewModel : ViewModel() {
isKpmConfigured = Natives.isKPMEnabled(), isKpmConfigured = Natives.isKPMEnabled(),
requireNewKernel = isManager && Natives.requireNewKernel() requireNewKernel = isManager && Natives.requireNewKernel()
) )
systemStatus = newStatus
systemStatusCache["status"] = newStatus
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error fetching system status", e) Log.e(TAG, "Error fetching system status", e)
} }
} }
} }
// 获取系统信息
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
private suspend fun fetchSystemInfo() { private suspend fun fetchSystemInfo() {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
@@ -235,7 +233,7 @@ class HomeViewModel : ViewModel() {
} }
} }
val newInfo = SystemInfo( systemInfo = SystemInfo(
kernelRelease = uname.release, kernelRelease = uname.release,
androidVersion = Build.VERSION.RELEASE, androidVersion = Build.VERSION.RELEASE,
deviceModel = getDeviceModel(), deviceModel = getDeviceModel(),
@@ -251,16 +249,12 @@ class HomeViewModel : ViewModel() {
moduleCount = getModuleCount(), moduleCount = getModuleCount(),
kpmModuleCount = getKpmModuleCount() kpmModuleCount = getKpmModuleCount()
) )
systemInfo = newInfo
systemInfoCache["info"] = newInfo
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error fetching system info", e) Log.e(TAG, "Error fetching system info", e)
} }
} }
} }
// 获取设备型号
@SuppressLint("PrivateApi") @SuppressLint("PrivateApi")
private fun getDeviceModel(): String { private fun getDeviceModel(): String {
return try { return try {
@@ -287,7 +281,6 @@ class HomeViewModel : ViewModel() {
} }
} }
// 获取管理器版本
private fun getManagerVersion(context: Context): Pair<String, Long> { private fun getManagerVersion(context: Context): Pair<String, Long> {
return try { return try {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!! val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!!

View File

@@ -1,5 +1,6 @@
[versions] [versions]
agp = "8.10.1" agp = "8.10.1"
gson = "2.11.0"
kotlin = "2.1.20" kotlin = "2.1.20"
ksp = "2.1.20-2.0.0" ksp = "2.1.20-2.0.0"
compose-bom = "2025.05.01" compose-bom = "2025.05.01"
@@ -62,6 +63,7 @@ com-github-topjohnwu-libsu-io = { group = "com.github.topjohnwu.libsu", name = "
dev-rikka-rikkax-parcelablelist = { module = "dev.rikka.rikkax.parcelablelist:parcelablelist", version.ref = "parcelablelist" } dev-rikka-rikkax-parcelablelist = { module = "dev.rikka.rikkax.parcelablelist:parcelablelist", version.ref = "parcelablelist" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
io-coil-kt-coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil-compose" } io-coil-kt-coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil-compose" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }