使用CameraX图像分析用例扫码后如何避免Intent被多次启动?
多次触发Intent的根因
- ML Kit的二维码识别是异步操作,你在
onSuccess里调用clearAnalyzer()只会停止后续新的帧提交给分析器,但已经进入异步处理队列的多个帧识别任务还是会陆续回调成功,触发多次onSuccess执行跳转逻辑 - 现有代码没有加状态锁,只要识别到符合条件的二维码就会触发回调,不会判断是否已经执行过跳转逻辑
解决方案
1. 增加执行状态锁,避免重复触发逻辑
在扫码Activity中新增布尔变量标记是否已经识别到二维码,只有未识别的状态下才执行跳转逻辑,识别成功后立刻锁死状态。
修改后的Activity侧代码:
// 扫码Activity顶部新增成员变量 private var isQRCodeDetected = false // 原来的onSuccess回调修改为: override fun onSuccess(qrString: String?) { // 先判断状态,已经识别过就直接返回 if (isQRCodeDetected || qrString == null) return isQRCodeDetected = true imageAnalysis.clearAnalyzer() Toast.makeText(this@ActivityQR,qrString,Toast.LENGTH_SHORT).show() Log.d("rty",qrString.toString()) val visitordetails = Intent(this@ActivityQR, DisplayQR::class.java) visitordetails.putExtra("VISITOR_QR", qrString) startActivity(visitordetails) // 可选:如果扫码页不需要保留,直接finish,彻底避免后续逻辑触发 finish() }
2. 优化CodeAnalyzer逻辑,提前终止无效帧处理
在分析器中也增加处理完成标记,收到成功回调后直接忽略后续所有帧,减少不必要的资源消耗,同时避免异步任务重复回调:
class CodeAnalyzer(context: Context, callBackInterface: CallBackInterface):ImageAnalysis.Analyzer { private val context: Context = context private val callback: CallBackInterface = callBackInterface // 新增处理完成标记 private var isProcessCompleted = false // 把BarcodeScanner改成成员变量,不要每次analyze都新建实例 private val scanner: BarcodeScanner = BarcodeScanning.getClient() @SuppressLint("UnsafeOptInUsageError") override fun analyze(image: ImageProxy) { // 已经处理完成就直接关闭图片返回,不做后续处理 if (isProcessCompleted) { image.close() return } val scannedIMage = image.image if (scannedIMage != null) { val scannedInputImage = InputImage.fromMediaImage( scannedIMage, image.imageInfo.rotationDegrees ) scanner.process(scannedInputImage).addOnSuccessListener { barCodes -> // 回调前也先判断状态,避免异步任务回调时已经处理完成 if (isProcessCompleted) return@addOnSuccessListener for (qrCode in barCodes) { when (qrCode.valueType) { Barcode.TYPE_TEXT -> { val qrString: String? = qrCode.rawValue if (qrString != null) { // 先标记处理完成,再回调 isProcessCompleted = true callback.onSuccess(qrString) } } } } }.addOnFailureListener { // 异常无需额外处理 }.addOnCompleteListener { image.close() } } else { image.close() } } }
3. 可选优化:配置Activity启动模式
如果多次跳转的是同一个DisplayQR页面,可以在AndroidManifest.xml里给DisplayQR设置android:launchMode="singleTop",这样栈顶已经是该Activity时不会重复创建新实例。
内容的提问来源于stack exchange,提问作者user14698807
相关产品推荐
相关产品推荐

