gpt4 book ai didi

flutter - StreamProvider 与 RiverPod 不工作(尝试从 Provider 迁移)

转载 作者:行者123 更新时间:2023-12-05 03:45:55 25 4
gpt4 key购买 nike

我试图通过将简单的 FireStore auth Provider 示例迁移到 RiverPod 来了解 RiverPod。

这是我的身份验证服务:

import 'package:firebase_auth/firebase_auth.dart';

class AuthenticationService {
final FirebaseAuth _firebaseAuth;
AuthenticationService(this._firebaseAuth);

// with StreamProvider we listen to these changes
Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();

Future<String> signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return 'Signed in';
} on FirebaseAuthException catch (e) {
return e.message;
}
}

Future<String> signUp({String email, String password}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return 'Signed up ';
} on FirebaseAuthException catch (e) {
return e.message;
}
}

Future<void> signOut() async {
await _firebaseAuth.signOut();
}
}

在 main.dart 中,我制作了 2 个提供程序,因此我可以使用该服务并监听 AuthenticationService 中的属性

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:meditatie_app/authentication_service.dart';
import 'package:meditatie_app/home_page.dart';
import 'package:meditatie_app/signin_page.dart';
import 'package:provider/provider.dart';

Future<void> main() async {
// initalize Firebase and before that we need to initialize the widgets.
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
// Normal provider to serve the AuthenticationService in the widgettree
// so the login form can use this provider to use .singIn()
Provider<AuthenticationService>(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
// also a StreamProvider that serves the AuthenticationSerivce authStateChanges
// this stream is updated by the FirebaseAuth package when users signin or out
// this provider use context.read<AuthenticationService> to find the
// provider dived here above
StreamProvider(
create: (context) =>
context.read<AuthenticationService>().authStateChanges,
)
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: AuthenticationWrapper(),
),
);
}
}

class AuthenticationWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User>();
if (firebaseUser != null) {
return HomePage();
}
return SignInPage();
}
}

这里是 SingIn 页面:

import 'package:flutter/material.dart';
import 'package:meditatie_app/authentication_service.dart';
import 'package:provider/provider.dart';

class SignInPage extends StatelessWidget {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();

...
RaisedButton(
onPressed: () {
// Sign in code
context.read<AuthenticationService>().signIn(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
},
...

这对普通的 Provider 工作正常,但我不能让它与 RiverPod 一起工作

我所做的是:

我在 providers.dart 中将这些提供程序设置为全局

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/all.dart';

import 'authentication_service.dart';

final authenticationSeriviceProvider =
Provider((ref) => AuthenticationService(FirebaseAuth.instance));
final authStateChangeProvider = StreamProvider.autoDispose<User>((ref) {
return ref
.watch(authenticationSeriviceProvider)
.authStateChanges;
});

这是正确的吗? authStateChangeProvider 正在使用 authenticationSeriviceProvider

什么时候使用它:

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:meditatie_app/home_page.dart';
import 'package:meditatie_app/signin_page.dart';
import 'package:flutter_riverpod/all.dart';
import 'providers.dart';

Future<void> main() async {
// initialize Firebase and before that we need to initialize the widgets.
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
// riverpod needs at toplevel a Provider container
// for storing state of different providers.
ProviderScope(
child: MyApp(),
),
);
}

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: AuthenticationWrapper(),
);
}
}

// Riverpods ConsumerWidget
// which can consume a provider
// rebuild if the value of the provider changes
class AuthenticationWrapper extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final firebaseUser = watch(authStateChangeProvider);
if (firebaseUser != null) {
return HomePage();
}
return SignInPage();
}
}

我的“firebaseUser”不再是一个用户,而是一个 AsyncValue

当我将其更改为:

class AuthenticationWrapper extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final User firebaseUser = watch(authStateChangeProvider).data?.value;
if (firebaseUser != null) {
return HomePage();
}
return SignInPage();
}
}

它正在工作,但是我现在使用 AsyncValue 做错了什么

最佳答案

扩展以前的答案 AsyncValue<T>是一个密封类,将其视为 Flutter 中的 StreamBuilder 具有 AsyncSnapshot<T>它包装了从流返回的值,并为您提供了检查其是否为 connecting 的选项。 , waiting , withErrorwithData .在你的情况下

class AuthenticationWrapper extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
return watch(authStateChangeProvider).when(
data: (user) => user == null ? SignInPage() : HomePage(),
loading: () => CircularProgressIndicator(),
error: (err, stack) => SignInPage(),
);
}
}

应该处理所有选项,现在加载时它会显示一个进度指示器,如果有错误(连接、错误结果等)它会显示 SignInPage,最后当有值时你仍然需要检查从 Stream 返回的值是否为 null(据我所知,当没有用户登录时 Firebase 返回 null,这并不意味着流为空)并显示正确的小部件,如果它是否为 null。

就像提供者一样,在检索到用户之后你仍然需要用它来做逻辑

关于flutter - StreamProvider 与 RiverPod 不工作(尝试从 Provider 迁移),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65587455/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com