使用GMS Vision的二维码扫描器在Firestore重复存储数据求助
解决GMS Vision扫码重复写入Firestore的问题
问题核心在于receiveDetections的触发机制:摄像头每帧识别到二维码时,这个回调就会被调用一次,短时间内会多次触发写入逻辑,导致Firestore中出现重复数据。以下是几种实用的解决方法:
方法1:记录已扫描内容,跳过重复写入
添加类成员变量存储最近扫描的内容,每次触发时先对比内容,仅当内容不同时执行写入:
// 类成员变量,保存最近一次扫描的二维码内容 private String lastScannedContent = ""; public void receiveDetections(Detector.Detections<Barcode> detections) { SparseArray<Barcode> qrcode = detections.getDetectedItems(); if(qrcode.size()!=0){ String currentContent = qrcode.valueAt(0).displayValue; // 对比当前内容与上次扫描内容,不同才执行写入 if (!currentContent.equals(lastScannedContent)) { lastScannedContent = currentContent; text.post(new Runnable() { @Override public void run() { text.setText(currentContent); Map<String, String> data = new HashMap<>(); data.put("Data", currentContent); db.collection("Records").add(data).addOnSuccessListener(documentReference -> { Toast.makeText(Scanner.this, "inserted", Toast.LENGTH_SHORT).show(); }); } }); } } }
方法2:扫描成功后暂停检测器
一旦完成扫描和写入,就暂停条码检测器,避免后续帧重复触发回调:
// 假设你已初始化BarcodeDetector实例 private BarcodeDetector barcodeDetector; public void receiveDetections(Detector.Detections<Barcode> detections) { SparseArray<Barcode> qrcode = detections.getDetectedItems(); if(qrcode.size()!=0){ // 先暂停检测器,阻止重复触发 barcodeDetector.release(); text.post(new Runnable() { @Override public void run() { String currentContent = qrcode.valueAt(0).displayValue; text.setText(currentContent); Map<String, String> data = new HashMap<>(); data.put("Data", currentContent); db.collection("Records").add(data).addOnSuccessListener(documentReference -> { Toast.makeText(Scanner.this, "inserted", Toast.LENGTH_SHORT).show(); // 若需恢复扫描,可在此重新初始化检测器 }); } }); } }
方法3:添加防抖延迟
设置固定延迟(如500ms),在延迟期间仅执行一次写入操作:
private Handler scanHandler = new Handler(); private Runnable writeTask; public void receiveDetections(Detector.Detections<Barcode> detections) { SparseArray<Barcode> qrcode = detections.getDetectedItems(); if(qrcode.size()!=0){ String currentContent = qrcode.valueAt(0).displayValue; // 移除之前未执行的延迟任务 scanHandler.removeCallbacks(writeTask); writeTask = () -> { text.post(() -> { text.setText(currentContent); Map<String, String> data = new HashMap<>(); data.put("Data", currentContent); db.collection("Records").add(data).addOnSuccessListener(documentReference -> { Toast.makeText(Scanner.this, "inserted", Toast.LENGTH_SHORT).show(); }); }); }; // 延迟500ms执行,确保只处理一次扫描结果 scanHandler.postDelayed(writeTask, 500); } }
你可以根据业务需求选择方案:需要持续扫描选方法1或3,仅需单次扫描选方法2。
内容的提问来源于stack exchange,提问作者Stacy Canencia
相关产品推荐
相关产品推荐

