From 001c7600cef0aebfb69ac2254e8aa26e175c870e Mon Sep 17 00:00:00 2001 From: MouseXu Date: Mon, 4 May 2026 15:35:34 +0800 Subject: [PATCH] fix: QR code ANR and memory leak - Port PR #291 from upstream: move login polling to IO thread - Use withFrameMillis for animation refresh - Add break point for Android < 12 animation loop - Fix memory leak: clear Drawable lists when colorScheme changes --- .../bv/viewmodel/login/AppQrLoginViewModel.kt | 2 +- .../dev/aaa1115910/m3qrcode/MaterialShapeQr.kt | 9 +++++++-- .../dev/aaa1115910/m3qrcode/MaterialShapeQrState.kt | 13 ++++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/login/AppQrLoginViewModel.kt b/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/login/AppQrLoginViewModel.kt index c93014bfd..c98174380 100644 --- a/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/login/AppQrLoginViewModel.kt +++ b/app/shared/src/main/kotlin/dev/aaa1115910/bv/viewmodel/login/AppQrLoginViewModel.kt @@ -49,7 +49,7 @@ class AppQrLoginViewModel( logger.info { qrLoginData.url } runCatching { timer.cancel() } timer = timeTask(1000, 1000, "check qr login result") { - viewModelScope.launch { + viewModelScope.launch(Dispatchers.IO) { checkLoginResult() } } diff --git a/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQr.kt b/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQr.kt index e357c4cd9..926c26030 100644 --- a/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQr.kt +++ b/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQr.kt @@ -14,6 +14,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.withFrameMillis import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale @@ -69,8 +70,12 @@ fun MaterialShapeQr( delay(50) continue } - state.frameElapsed = System.currentTimeMillis() - state.qrStartTime - delay(16) + withFrameMillis { + state.frameElapsed = System.currentTimeMillis() - state.qrStartTime + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S && state.hasFinalDataImage) { + break + } } } diff --git a/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQrState.kt b/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQrState.kt index 1135672b2..1ab363bf1 100644 --- a/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQrState.kt +++ b/app/shared/src/main/kotlin/dev/aaa1115910/m3qrcode/MaterialShapeQrState.kt @@ -673,7 +673,18 @@ internal fun rememberMaterialShapeQrState( colorMap[".dot3"] = backgroundDotColor3 } - LaunchedEffect(Unit) { + LaunchedEffect(colorScheme) { + // 清理旧的 Drawable 引用 + arrayOf1x1Shapes.clear() + arrayOf1x1SemiCircleShapes.clear() + arrayOf2x2Shapes.clear() + arrayOf3x3Shapes.clear() + arrayOf7x7Shapes.clear() + arrayOfHorizontalBarShapes.clear() + arrayOfHorizontalHalfCapsuleBarShapes.clear() + arrayOfVerticalBarShapes.clear() + arrayOfFinderPatternCenterShapes.clear() + loadDrawables() applyLottieDynamicColor() }