perf(image): 优化图片加载性能
- 使用 BitmapDecodeHelper 替换 BitmapFactory 进行采样解码 - 添加单线程执行器进行异步图片解码处理 - 实现图片视图布局完成后再进行尺寸计算和加载 - 防止因 Activity 销毁导致的内存泄漏问题 - 在 SprayingFinishActivity、SprayingOCRActivity 和 SprayingResultActivity 中统一图片加载逻辑
这个提交包含在:
父节点
ff6a0c3a33
当前提交
7310127d56
@ -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<ItemItem, SprayingFinishVM, ActivitySprayingFinishBinding>() {
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<ItemItem> = 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) {
|
||||
|
||||
@ -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<ItemItem> = 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户