diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/CollectFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/CollectFragment.kt index 35e8957..8d4f162 100644 --- a/app/src/main/java/com/sw/dualscreen/activity/fragment/CollectFragment.kt +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/CollectFragment.kt @@ -98,15 +98,16 @@ class CollectFragment : BaseFragment() { } - private val cameraCallback: (Uri) -> Unit = cameraCallback@{ uri -> + private val cameraCallback: (Uri) -> Unit = { uri -> try { - val index = foodCollectionList.indexOfFirst { it.imageFile == null } - if (index == -1) { - ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") - settingActivity?.hideWaitingDialog() - return@cameraCallback - } activity?.lifecycleScope?.launch(Dispatchers.Main) { + // 主线程原子操作:查找空闲槽位并立即标记,避免竞态 + val index = foodCollectionList.indexOfFirst { it.isShowCamera } + if (index == -1) { + ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") + settingActivity?.hideWaitingDialog() + return@launch + } foodCollectionList[index].let { it.imageVector = null it.bitmap = null @@ -115,11 +116,11 @@ class CollectFragment : BaseFragment() { it.imageUri = uri } collectionAdapter.notifyItemChanged(index) - } -// settingActivity?.hideWaitingDialog() - activity?.lifecycleScope?.launch(Dispatchers.IO) { - ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap -> - getImageVector(index, bitmap) + // IO线程处理bitmap + launch(Dispatchers.IO) { + ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap -> + getImageVector(index, bitmap) + } } } } catch (e: Exception) { @@ -130,6 +131,10 @@ class CollectFragment : BaseFragment() { } } + private val photoFailCallback: (String) -> Unit = { errMsg -> + settingActivity?.hideWaitingDialog() + } + private fun getImageVector(index: Int, bitmap: Bitmap) { // val bitmap = BitmapCropper.cropCenter( // original = srcBmp, @@ -171,13 +176,7 @@ class CollectFragment : BaseFragment() { } settingActivity?.showWaitingDialog("采集中……") - cameraUtils.takePhoto(succCallback = { uri -> - settingActivity?.lifecycleScope?.launch((Dispatchers.IO)) { - cameraCallback(uri) - } - }, failCallback = { errMsg -> - settingActivity?.hideWaitingDialog() - }) + cameraUtils.takePhoto(succCallback = cameraCallback, failCallback = photoFailCallback) } private var cameraErrorCount = 0 diff --git a/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt b/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt index 3bb0d13..72702ba 100644 --- a/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt +++ b/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt @@ -40,7 +40,7 @@ class FoodCollectionAdapter (var list: MutableList) : //setImageURI(it.imageUri) //setImageBitmap(it.bitmap) if (it.imageUri!=null) { - setImageURI(it.imageUri) + load(it.imageUri) } else { load(it.imageFile) } diff --git a/app/src/main/java/com/sw/dualscreen/utils/PhotoCaptureHelper.kt b/app/src/main/java/com/sw/dualscreen/utils/PhotoCaptureHelper.kt index f58d1f0..95d13f8 100644 --- a/app/src/main/java/com/sw/dualscreen/utils/PhotoCaptureHelper.kt +++ b/app/src/main/java/com/sw/dualscreen/utils/PhotoCaptureHelper.kt @@ -2,6 +2,8 @@ package com.sw.dualscreen.utils import android.content.Context import android.net.Uri +import android.os.Handler +import android.os.Looper import androidx.core.content.FileProvider import androidx.camera.core.ImageCapture import androidx.camera.core.ImageCaptureException @@ -42,7 +44,8 @@ class PhotoCaptureHelper( */ fun takePhoto( fileNamePrefix: String = "IMG_", - fileExtension: String = ".jpg" + fileExtension: String = ".jpg", + isRetry: Boolean = false ) { Timber.d("开始拍照采集") @@ -70,13 +73,16 @@ class PhotoCaptureHelper( } override fun onError(exception: ImageCaptureException) { + Timber.e(exception) val errorMsg = "拍照失败: ${exception.message}" - if (errorMsg.contains("Not bound to a valid Camera")) { - if (bindCamera != null) { - bindCamera?.invoke() - //takePhoto() - } - + if (errorMsg.contains("Not bound to a valid Camera") && !isRetry) { + Timber.w(exception, "相机未绑定,尝试重新绑定后重试") + bindCamera?.invoke() + // 延迟重试,等待相机异步绑定完成 + Handler(Looper.getMainLooper()).postDelayed({ + takePhoto(fileNamePrefix, fileExtension, isRetry = true) + }, 300) + return } Timber.e(exception, errorMsg) onError(errorMsg)