Flutter中如何通过Firebase校验UID后触发对话框获取用户邮箱?
实现方案
核心逻辑拆分
对话框属于UI交互操作,必须在StatefulWidget中处理(需要管理输入框的状态),你的Firebase类作为业务逻辑层,只负责数据的查询与写入,不应该直接处理UI操作。正确流程是:
- UI层触发UID查询
- 根据Firebase返回的结果,判断是否需要弹出对话框
- 获取用户输入的邮箱后,调用Firebase类的写入方法完成数据存储
步骤1:重构Firebase类
把写入操作拆分为独立方法,接收uid和email参数,让UI层可以传入用户输入的邮箱:
import 'package:firebase_database/firebase_database.dart'; import 'data_processing.dart'; class FirebaseService { // 改名避免和Firebase官方包类名冲突 DatabaseReference ref = FirebaseDatabase.instance.ref(); // 查询UID是否存在,返回布尔结果 Future<bool> isUidExists(String uid) async { final snapshot = await ref.child('S_ID/$uid').get(); return snapshot.exists; } // 写入新UID对应的用户数据 Future<void> writeNewUidData(String uid, String email) async { String lastUpdatedDate = DataProcessing.getCurrentDate(); int lastUpdatedHour = DataProcessing.getCurrentHour(); String volumeLeft = "350.00"; DatabaseReference userRef = ref.child("S_ID/$uid"); await userRef.set({ "Email Address": email, "Last Updated Date": lastUpdatedDate, "Last Updated Time": lastUpdatedHour, "Volume Left": volumeLeft }); } // 处理蓝牙传入的UID列表 Future<void> processUid(List<int> intList) async { if (intList.isEmpty) { print('列表为空'); return; } String myUID = intList.first.toString(); print('UID: $myUID'); } }
步骤2:在UI层处理弹窗逻辑
在主页面(比如main.dart中的StatefulWidget)中,调用Firebase的查询方法,根据结果触发对话框:
import 'package:flutter/material.dart'; import 'firebase_service.dart'; // 导入重构后的Firebase类 void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: const BluetoothDataScreen(), ); } } class BluetoothDataScreen extends StatefulWidget { const BluetoothDataScreen({super.key}); @override State<BluetoothDataScreen> createState() => _BluetoothDataScreenState(); } class _BluetoothDataScreenState extends State<BluetoothDataScreen> { final FirebaseService _firebaseService = FirebaseService(); // 模拟蓝牙接收到数据后的处理方法 Future<void> handleBluetoothData(List<int> intList) async { if (intList.isEmpty) return; String uid = intList.first.toString(); bool uidExists = await _firebaseService.isUidExists(uid); if (!uidExists) { // 弹出对话框获取邮箱 _showEmailInputDialog(uid); } else { // UID存在的后续处理 print('UID已存在'); } } void _showEmailInputDialog(String uid) { TextEditingController emailController = TextEditingController(); showDialog( context: context, barrierDismissible: false, // 必须输入邮箱才能关闭 builder: (context) => AlertDialog( title: const Text('绑定邮箱'), content: TextField( controller: emailController, keyboardType: TextInputType.emailAddress, decoration: const InputDecoration(hintText: '请输入你的邮箱'), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () async { String email = emailController.text.trim(); if (email.isNotEmpty) { // 调用Firebase写入方法 await _firebaseService.writeNewUidData(uid, email); Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('绑定成功')), ); } }, child: const Text('确认'), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('蓝牙传感器数据处理')), body: Center( // 这里可以替换为蓝牙连接UI或实际触发数据处理的逻辑 child: ElevatedButton( onPressed: () { // 模拟接收到蓝牙数据,传入测试UID列表 handleBluetoothData([12345]); }, child: const Text('测试处理数据'), ), ), ); } }
关键说明
- 用StatefulWidget的原因:对话框的输入框需要
TextEditingController管理状态,StatelessWidget无法持有可变状态。 - 业务层与UI层解耦:Firebase类只处理数据逻辑,UI层负责交互,后续修改任一模块都不会影响另一模块,代码更易维护。
内容的提问来源于stack exchange,提问作者Danidu Jayathilaka
相关产品推荐
相关产品推荐

