From 7310127d568d6fa9f3471903c8ea96d6969dc252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=8B=A4=E6=B0=91?= Date: Tue, 14 Apr 2026 22:59:25 +0800 Subject: [PATCH] =?UTF-8?q?perf(image):=20=E4=BC=98=E5=8C=96=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E5=8A=A0=E8=BD=BD=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 BitmapDecodeHelper 替换 BitmapFactory 进行采样解码 - 添加单线程执行器进行异步图片解码处理 - 实现图片视图布局完成后再进行尺寸计算和加载 - 防止因 Activity 销毁导致的内存泄漏问题 - 在 SprayingFinishActivity、SprayingOCRActivity 和 SprayingResultActivity 中统一图片加载逻辑 --- .../brain/glass/ui/SprayingFinishActivity.kt | 21 +++++++++++++++-- .../brain/glass/ui/SprayingOCRActivity.kt | 21 ++++++++++++++--- .../brain/glass/ui/SprayingResultActivity.kt | 23 +++++++++++++++++-- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/nova/brain/glass/ui/SprayingFinishActivity.kt b/app/src/main/java/com/nova/brain/glass/ui/SprayingFinishActivity.kt index fc2b6ed..50af875 100644 --- a/app/src/main/java/com/nova/brain/glass/ui/SprayingFinishActivity.kt +++ b/app/src/main/java/com/nova/brain/glass/ui/SprayingFinishActivity.kt @@ -2,10 +2,11 @@ package com.nova.brain.glass.ui import android.app.Activity import android.content.Intent -import android.graphics.BitmapFactory +import androidx.core.view.doOnLayout import androidx.recyclerview.widget.RecyclerView import com.nova.brain.glass.R import com.nova.brain.glass.databinding.ActivitySprayingFinishBinding +import com.nova.brain.glass.helper.BitmapDecodeHelper import com.nova.brain.glass.helper.OfflineCmdListener import com.nova.brain.glass.helper.OfflineCmdServiceHelper import com.nova.brain.glass.helper.SprayingPhotoManager @@ -15,6 +16,7 @@ import com.xuqm.base.adapter.BasePagedAdapter import com.xuqm.base.adapter.CommonPagedAdapter import com.xuqm.base.adapter.ViewHolder import com.xuqm.base.ui.BaseListFormLayoutNormalActivity +import java.util.concurrent.Executors class SprayingFinishActivity : BaseListFormLayoutNormalActivity() { @@ -22,6 +24,7 @@ class SprayingFinishActivity : override fun fullscreen(): Boolean = true override fun getRecyclerOrientation(): Int = RecyclerView.VERTICAL + private val imageDecodeExecutor = Executors.newSingleThreadExecutor() private val listener = object : OfflineCmdListener { override fun onOfflineCmd(cmd: String) { @@ -52,7 +55,21 @@ class SprayingFinishActivity : val imageViews = listOf(binding.photo1, binding.photo2, binding.photo3) imageViews.forEach { it.setImageDrawable(null) } photos.forEachIndexed { index, path -> - imageViews.getOrNull(index)?.setImageBitmap(BitmapFactory.decodeFile(path)) + imageViews.getOrNull(index)?.let { imageView -> + imageView.doOnLayout { + val targetWidth = imageView.width.coerceAtLeast(1) + val targetHeight = imageView.height.coerceAtLeast(1) + imageDecodeExecutor.execute { + val bitmap = BitmapDecodeHelper.decodeSampledBitmap(path, targetWidth, targetHeight) + runOnUiThread { + if (isFinishing || isDestroyed) { + return@runOnUiThread + } + imageView.setImageBitmap(bitmap) + } + } + } + } } } diff --git a/app/src/main/java/com/nova/brain/glass/ui/SprayingOCRActivity.kt b/app/src/main/java/com/nova/brain/glass/ui/SprayingOCRActivity.kt index 04fc518..ff2d047 100644 --- a/app/src/main/java/com/nova/brain/glass/ui/SprayingOCRActivity.kt +++ b/app/src/main/java/com/nova/brain/glass/ui/SprayingOCRActivity.kt @@ -1,13 +1,14 @@ package com.nova.brain.glass.ui import android.content.Intent -import android.graphics.BitmapFactory import android.os.CountDownTimer import android.os.Environment import android.view.WindowManager +import androidx.core.view.doOnLayout import androidx.recyclerview.widget.RecyclerView import com.nova.brain.glass.R import com.nova.brain.glass.databinding.ActivitySprayingOcrBinding +import com.nova.brain.glass.helper.BitmapDecodeHelper import com.nova.brain.glass.helper.OfflineCmdListener import com.nova.brain.glass.helper.OfflineCmdServiceHelper import com.nova.brain.glass.helper.SprayingPhotoManager @@ -24,6 +25,7 @@ import com.xuqm.base.common.LogHelper import com.xuqm.base.extensions.showMessage import com.xuqm.base.ui.BaseListFormLayoutNormalActivity import java.io.File +import java.util.concurrent.Executors import java.util.UUID class SprayingOCRActivity : @@ -63,6 +65,7 @@ class SprayingOCRActivity : } private val photoCallbackId = UUID.randomUUID().toString() private var resultCountdown: CountDownTimer? = null + private val imageDecodeExecutor = Executors.newSingleThreadExecutor() private val mPhotoFileCallback = object : PhotoFileCallback.Stub() { override fun onTakePhoto(path: String) { @@ -139,8 +142,20 @@ class SprayingOCRActivity : override fun adapter(): BasePagedAdapter = adapter private fun showPhoto(path: String) { - binding.content.setImageBitmap(BitmapFactory.decodeFile(path)) - restartResultCountdown(path) + binding.content.doOnLayout { + val targetWidth = it.width.coerceAtLeast(1) + val targetHeight = it.height.coerceAtLeast(1) + imageDecodeExecutor.execute { + val bitmap = BitmapDecodeHelper.decodeSampledBitmap(path, targetWidth, targetHeight) + runOnUiThread { + if (isFinishing || isDestroyed) { + return@runOnUiThread + } + binding.content.setImageBitmap(bitmap) + restartResultCountdown(path) + } + } + } } private fun restartResultCountdown(path: String) { diff --git a/app/src/main/java/com/nova/brain/glass/ui/SprayingResultActivity.kt b/app/src/main/java/com/nova/brain/glass/ui/SprayingResultActivity.kt index 7af5615..d749d5c 100644 --- a/app/src/main/java/com/nova/brain/glass/ui/SprayingResultActivity.kt +++ b/app/src/main/java/com/nova/brain/glass/ui/SprayingResultActivity.kt @@ -2,14 +2,15 @@ package com.nova.brain.glass.ui import android.app.Activity import android.content.Intent -import android.graphics.BitmapFactory import android.graphics.Paint import android.os.Environment import android.view.WindowManager import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.view.doOnLayout import androidx.recyclerview.widget.RecyclerView import com.nova.brain.glass.R import com.nova.brain.glass.databinding.ActivitySprayingResultBinding +import com.nova.brain.glass.helper.BitmapDecodeHelper import com.nova.brain.glass.helper.OfflineCmdListener import com.nova.brain.glass.helper.OfflineCmdServiceHelper import com.nova.brain.glass.helper.SprayingPhotoManager @@ -25,6 +26,7 @@ import com.xuqm.base.common.LogHelper import com.xuqm.base.extensions.showMessage import com.xuqm.base.ui.BaseListFormLayoutNormalActivity import java.io.File +import java.util.concurrent.Executors import java.util.UUID class SprayingResultActivity : @@ -33,6 +35,7 @@ class SprayingResultActivity : override fun fullscreen(): Boolean = true override fun getRecyclerOrientation(): Int = RecyclerView.HORIZONTAL + private val imageDecodeExecutor = Executors.newSingleThreadExecutor() private var status = true private val manualResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> @@ -157,7 +160,7 @@ class SprayingResultActivity : super.initData() window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) intent.getStringExtra("path")?.apply { - binding.iv.setImageBitmap(BitmapFactory.decodeFile(this)) + showResultImage(this) setStatusImage() } } @@ -231,4 +234,20 @@ class SprayingResultActivity : } override fun adapter(): BasePagedAdapter = adapter + + private fun showResultImage(path: String) { + binding.iv.doOnLayout { + val targetWidth = it.width.coerceAtLeast(1) + val targetHeight = it.height.coerceAtLeast(1) + imageDecodeExecutor.execute { + val bitmap = BitmapDecodeHelper.decodeSampledBitmap(path, targetWidth, targetHeight) + runOnUiThread { + if (isFinishing || isDestroyed) { + return@runOnUiThread + } + binding.iv.setImageBitmap(bitmap) + } + } + } + } }