在 Flutter 中收听 Stream 并只向 DB 写入一次

Dul*_*nka 5 qr-code dart flutter sqflite

我正在开发一个二维码阅读器应用程序,我使用一个外部二维码阅读器包 ( https://pub.dev/packages/qr_code_scanner )。它侦听 Stream 并返回 QR 数据。但是当我将数据写入 sqlite 数据库时,它会多次写入相同的数据,因为它不会停止监听 Stream。我不认为取消订阅流是一个好主意,因为在从 url 启动或关闭对话框返回后,我仍然需要流来收听。如果我错了,请纠正我并提出解决方案,谢谢。

void _onQRViewCreated(QRViewController controller) {
    this.controller = controller;
    controller.scannedDataStream.listen((scanData) async {
      
      setState(() {
        qrData = scanData;
      });
  
      if (await canLaunch(qrData)) {
        var status = await launch(qrData);

        if(status){
          final data = QrModel(
            content: scanData,
            date: DateFormat.yMMMd().add_jm().format(DateTime.now()),
          );
          await dbProvider.addData(data);
        }

      } else {

        if (!alertBoxOpen) {

          final data = QrModel(
            content: scanData,
            date: DateFormat.yMMMd().add_jm().format(DateTime.now()),
          );
          await dbProvider.addData(data);

          setState(() => alertBoxOpen = true);
          
          showDialog(
              context: context,
              builder: (context) {
                return AlertDialog(
                  content: Text(qrData),
                  actions: [
                    MaterialButton(
                        child: Text('OK',
                            style: TextStyle(
                                fontSize: 18.0, fontWeight: FontWeight.bold)),
                        onPressed: () {
                          setState(() => alertBoxOpen = false);
                          Navigator.of(context).pop();
                        }),
                  ],
                );
              });
        }
      }
    });
    
  }
Run Code Online (Sandbox Code Playgroud)

Dul*_*nka 0

我为此实施了一个解决方法。我将从流返回的值分配scanData给变量qrData并添加到数据库,如果qrData != scanData

void _onQRViewCreated(QRViewController controller) {
    this.controller = controller;

    controller.scannedDataStream.listen((scanData) async {
      if (await canLaunch(scanData)) {
        await launch(scanData);

        if (qrData != scanData) {
          setState(() {
            qrData = scanData;
          });
          final data = QrModel(
            content: scanData,
            date: DateFormat.yMMMd().add_jm().format(DateTime.now()),
          );
          await dbProvider.addData(data);
        }
      } else {
        if (!alertBoxOpen) {
          if (qrData != scanData) {
            setState(() {
              qrData = scanData;
            });
            final data = QrModel(
              content: scanData,
              date: DateFormat.yMMMd().add_jm().format(DateTime.now()),
            );
            await dbProvider.addData(data);
          }

          setState(() => alertBoxOpen = true);

          showDialog(
              context: context,
              builder: (context) {
                return AlertDialog(
                  content: Text(qrData),
                  actions: [
                    MaterialButton(
                        child: Text('OK',
                            style: TextStyle(
                                fontSize: 18.0, fontWeight: FontWeight.bold)),
                        onPressed: () {
                          setState(() => alertBoxOpen = false);
                          Navigator.of(context).pop();
                        }),
                  ],
                );
              });
        }
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)