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

Flutter中无法通过Firebase-Auth与Provider全局提供自定义User类

解决方案

核心思路

  1. 用StreamProvider处理异步逻辑:它能监听数据流并自动更新UI,无需在BuildContext中直接调用异步函数。
  2. 封装Firebase操作到独立服务类:把用户数据的获取/创建逻辑从Provider中分离,降低代码耦合度。
  3. 全局初始化Provider:在main.dart中用MultiProvider注入服务和数据流,确保应用启动时就触发Firebase操作。

代码实现

1. 自定义User类(models.dart)

import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class CustomUser {
  final String uid;
  final String name;
  final String email;

  CustomUser({required this.uid, required this.name, required this.email});

  factory CustomUser.fromJson(Map<String, dynamic> json) => _$CustomUserFromJson(json);
  Map<String, dynamic> toJson() => _$CustomUserToJson(this);
}

2. 用户服务类(user_service.dart)

封装Firebase Auth和数据库操作:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'models.dart';

class UserService {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final DatabaseReference _dbRef = FirebaseDatabase.instance.ref('users');

  // 获取或创建用户(单次操作)
  Future<CustomUser?> getOrCreateUser() async {
    final firebaseUser = _auth.currentUser;
    if (firebaseUser == null) return null;

    final event = await _dbRef.child(firebaseUser.uid).once();
    if (event.snapshot.exists) {
      return CustomUser.fromJson(event.snapshot.value as Map<String, dynamic>);
    } else {
      final newUser = CustomUser(
        uid: firebaseUser.uid,
        name: firebaseUser.displayName ?? '未知用户',
        email: firebaseUser.email ?? ''
      );
      await _dbRef.child(firebaseUser.uid).set(newUser.toJson());
      return newUser;
    }
  }

  // 监听用户数据变化(实时更新)
  Stream<CustomUser?> listenToUser() {
    return _auth.authStateChanges().asyncMap((firebaseUser) async {
      if (firebaseUser == null) return null;
      final event = await _dbRef.child(firebaseUser.uid).once();
      if (event.snapshot.exists) {
        return CustomUser.fromJson(event.snapshot.value as Map<String, dynamic>);
      } else {
        final newUser = CustomUser(
          uid: firebaseUser.uid,
          name: firebaseUser.displayName ?? '未知用户',
          email: firebaseUser.email ?? ''
        );
        await _dbRef.child(firebaseUser.uid).set(newUser.toJson());
        return newUser;
      }
    });
  }
}

3. 全局Provider配置(main.dart)

用MultiProvider注入服务和数据流,确保全局可访问:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:firebase_core/firebase_core.dart';
import 'user_service.dart';
import 'models.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider(create: (_) => UserService()),
        StreamProvider<CustomUser?>(
          create: (context) => context.read<UserService>().listenToUser(),
          initialData: null,
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Firebase User Demo',
        home: const HomeScreen(),
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final user = context.watch<CustomUser?>();
    return Scaffold(
      appBar: AppBar(title: const Text('用户信息')),
      body: Center(
        child: user == null
            ? const CircularProgressIndicator()
            : Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('UID: ${user.uid}'),
                  Text('姓名: ${user.name}'),
                  Text('邮箱: ${user.email}'),
                ],
              ),
      ),
    );
  }
}

关键说明

  • StreamProvider会自动监听Firebase Auth的状态变化,当用户登录/登出时,自动触发数据库的读写操作,更新全局的CustomUser实例。
  • 所有Firebase逻辑都封装在UserService中,Provider只负责数据流的分发,代码结构更清晰。
  • 在main.dart中初始化Provider后,任何页面都可以通过context.watch<CustomUser?>()获取最新的用户数据。

内容的提问来源于stack exchange,提问作者Eric Kemmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:15:02