Skip to content

Commit

Permalink
perf: updateAppInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Nov 30, 2024
1 parent 9e82967 commit 00dffbe
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import li.songe.gkd.appScope
import li.songe.gkd.shizuku.shizukuCheckGranted
import li.songe.gkd.util.initOrResetAppInfoCache
import li.songe.gkd.util.launchTry
import li.songe.gkd.util.mayQueryPkgNoAccessFlow
import li.songe.gkd.util.toast
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
Expand Down Expand Up @@ -184,7 +185,7 @@ fun updatePermissionState() {
writeSecureSettingsState,
shizukuOkState,
).forEach { it.updateAndGet() }
if (canQueryPkgState.stateFlow.value != canQueryPkgState.updateAndGet()) {
if (canQueryPkgState.stateFlow.value != canQueryPkgState.updateAndGet() || mayQueryPkgNoAccessFlow.value) {
appScope.launchTry {
initOrResetAppInfoCache()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fun QueryPkgAuthCard() {
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = if (!canQueryPkg) "如需显示所有应用\n请授予[读取应用列表权限]" else "检测到应用数量过少\n可尝试授予[读取应用列表权限]",
text = if (!canQueryPkg) "如需显示所有应用\n请授予[读取应用列表权限]" else "检测到应用数量过少\n可尝试授予[读取应用列表权限]\n或关闭权限后重新授权",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
Expand All @@ -72,6 +72,7 @@ fun QueryPkgAuthCard() {
})) {
Text(text = "申请权限")
}
Spacer(modifier = Modifier.height(EmptyHeight / 2))
}
}
}
51 changes: 32 additions & 19 deletions app/src/main/kotlin/li/songe/gkd/util/AppInfoState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import android.os.Build
import com.blankj.utilcode.util.LogUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -38,23 +41,25 @@ val orderedAppInfosFlow by lazy {

// https://github.com/orgs/gkd-kit/discussions/761
// 某些设备在应用更新后出现权限错乱/缓存错乱
private const val MINIMUM_NORMAL_APP_SIZE = 8
val mayQueryPkgNoAccessFlow by lazy {
appInfoCacheFlow.map(appScope) { c ->
c.values.count { a -> !a.isSystem && !a.hidden && a.id != META.appId } < 8
c.values.count { a -> !a.isSystem && !a.hidden && a.id != META.appId } < MINIMUM_NORMAL_APP_SIZE
}
}

private val willUpdateAppIds by lazy { MutableStateFlow(emptySet<String>()) }

private val packageReceiver by lazy {
object : BroadcastReceiver() {
/**
* 例: 小米应用商店更新应用产生连续 3个事件: PACKAGE_REMOVED->PACKAGE_ADDED->PACKAGE_REPLACED
*
*/
override fun onReceive(context: Context?, intent: Intent?) {
val appId = intent?.data?.schemeSpecificPart ?: return
if (intent.action == Intent.ACTION_PACKAGE_ADDED || intent.action == Intent.ACTION_PACKAGE_REPLACED || intent.action == Intent.ACTION_PACKAGE_REMOVED) {
// update
updateAppInfo(appId)
/**
* 例: 小米应用商店更新应用产生连续 3个事件: PACKAGE_REMOVED->PACKAGE_ADDED->PACKAGE_REPLACED
* 使用 Flow + debounce 优化合并
*/
willUpdateAppIds.update { it + appId }
}
}
}.apply {
Expand All @@ -79,26 +84,31 @@ private val packageReceiver by lazy {
}
}

private fun getAppInfo(appId: String): AppInfo? {
return try {
app.packageManager.getPackageInfo(appId, 0)
} catch (_: PackageManager.NameNotFoundException) {
null
}?.toAppInfo()
}

private val updateAppMutex by lazy { Mutex() }

private fun updateAppInfo(appId: String) {
appScope.launchTry(Dispatchers.IO) {
val packageManager = app.packageManager
updateAppMutex.withLock {
val newMap = appInfoCacheFlow.value.toMutableMap()
val info = try {
packageManager.getPackageInfo(appId, 0)
} catch (_: PackageManager.NameNotFoundException) {
null
}
private suspend fun updateAppInfo(appIds: Set<String>) {
if (appIds.isEmpty()) return
willUpdateAppIds.update { it - appIds }
updateAppMutex.withLock {
LogUtils.d("updateAppInfo", appIds)
val newMap = appInfoCacheFlow.value.toMutableMap()
appIds.forEach { appId ->
val info = getAppInfo(appId)
if (info != null) {
newMap[appId] = info.toAppInfo()
newMap[appId] = info
} else {
newMap.remove(appId)
}
appInfoCacheFlow.value = newMap
}
appInfoCacheFlow.value = newMap
}
}

Expand Down Expand Up @@ -128,5 +138,8 @@ fun initAppState() {
packageReceiver
appScope.launchTry(Dispatchers.IO) {
initOrResetAppInfoCache()
willUpdateAppIds.debounce(1000)
.filter { it.isNotEmpty() }
.collect { updateAppInfo(it) }
}
}

0 comments on commit 00dffbe

Please sign in to comment.