FlutterでQRコードを読み込む（riverpod 2）

# はじめに
QRコードを読み取るアプリを作る機会があったので、ライブラリを探っていたら `qr_code_scanner` っていう良さげなものがあったので、使わせていただきました。
exampleが `StatefulWidget` で書かれていたのですが、`riverpod`を使っていたので書き換えたバージョンを紹介します。
カメラ権限周りの記述については割愛しています。

https://pub.dev/packages/qr_code_scanner

# 環境
```shell
% fvm flutter --version
Flutter 3.3.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision d9111f6402 (9 weeks ago) • 2022-10-19 12:27:13 -0700
Engine • revision 3ad69d7be3
Tools • Dart 2.18.2 • DevTools 2.15.0
```

# ソース
```dart@pubspec.yaml
environment:
  sdk: '>=2.18.2 <3.0.0'

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations: 
    sdk: flutter

  flutter_riverpod: ^2.0.2
  qr_code_scanner: ^1.0.1
```

```dart@qr_code_reader_page.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';

final qrCodeProvider =
    StateNotifierProvider.autoDispose<QRCodeNotifier, Barcode>((ref) {
  final notifier = QRCodeNotifier();
  ref.onDispose(() => notifier.controller?.dispose());
  return notifier;
});

class QRCodeNotifier extends StateNotifier<Barcode> {
  QRViewController? controller;
  QRCodeNotifier() : super(Barcode(null, BarcodeFormat.unknown, null));

  void onQRViewCreated(QRViewController controller) {
    this.controller = controller;
    this.controller!.scannedDataStream.listen((scanData) {
      state = scanData;
    });
  }
}

class QRCodeReaderPage extends ConsumerWidget {
  final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');

  QRCodeReaderPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final notifier = ref.watch(qrCodeProvider.notifier);
    final state = ref.watch(qrCodeProvider);
    final double scanArea = (MediaQuery.of(context).size.width < 400 ||
            MediaQuery.of(context).size.height < 400)
        ? 150.0
        : 300.0;
    return Scaffold(
      body: Column(
        children: [
          Expanded(
              flex: 4,
              child: QRView(
                key: qrKey,
                onQRViewCreated: notifier.onQRViewCreated,
                overlay: QrScannerOverlayShape(
                    borderColor: Colors.red,
                    borderRadius: 10,
                    borderLength: 30,
                    borderWidth: 10,
                    cutOutSize: scanArea),
                onPermissionSet: (ctrl, p) =>
                    _onPermissionSet(context, ctrl, p),
              )),
          Expanded(
              flex: 1,
              child: FittedBox(
                fit: BoxFit.contain,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    if (state.format != BarcodeFormat.unknown)
                      Text(
                          'Barcode Type: ${describeEnum(state.format)}   Data: ${state.code}')
                    else
                      const Text('Scan a code'),
                  ],
                ),
              ))
        ],
      ),
    );
  }

  void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
    debugPrint('${DateTime.now().toIso8601String()}_onPermissionSet $p');
    if (!p) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('no Permission')),
      );
    }
  }
}
```

最近主流？になりつつある `riverpod` ですが、私のように書き方に苦労している人がいると思ったので紹介してみました。
必要最低限のコードですが、何かの役に立てば幸いです。