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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:36:12