You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:15:40