颤振:找不到正确的提供者

Posted

技术标签:

【中文标题】颤振:找不到正确的提供者【英文标题】:Flutter : Could not find the correct Provider 【发布时间】:2020-06-04 14:40:18 【问题描述】:

provider 的帮助下,我准备在我的flutter 应用程序中实现Firebase Authentication。首先,我正在检查用户是否已经登录,如果是,我将他发送到 home 屏幕。否则,我会将他发送到 登录 屏幕。

请检查我下面的代码。

ma​​in.dart

import 'package:flutter/material.dart';
import 'package:customer/services/auth.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
    // This widget is the root of your application.
    @override
    Widget build(BuildContext context) 
        return ChangeNotifierProvider(
            child: MaterialApp(
                title: 'Customer App',

                home: AuthWrapper(), 
                routes: 
                    '/account': (context) => AccountPage(),
                ,
            ), create: (BuildContext context) 
                AuthService();
            ,
        );
    

auth.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

class AuthService with ChangeNotifier

  final FirebaseAuth _auth = FirebaseAuth.instance;
  FirebaseUser _user=null;

//Sign in with username and password
  Future signInWithEmail(String email, String password) async 
    FirebaseUser user;

    try 
      AuthResult result = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
          user = result.user;

      if (user != null) 
        print("Sign in success: " + user.email);
        _user = user;
       else 
        print("sign in failed");
        _user = null;
      
     catch (e) 
      print(e.toString());
    
    finally
      notifyListeners();
    
  

//Get the current user
  FirebaseUser getCurrentUser()  
    return _user;
  


auth_wrapper.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:customer/pages/home.dart';
import 'package:customer/pages/login.dart';
import 'package:customer/services/auth.dart';
import 'package:provider/provider.dart';

class AuthWrapper extends StatelessWidget 
  AuthWrapper() 

  @override
  Widget build(BuildContext context) 
    var currentUser =Provider.of<AuthService>(context, listen: false).getCurrentUser();

    if (currentUser == null) 
      return LoginPage();
     else 
      return HomePage();
    
  

不幸的是,当我运行这个应用程序时,我收到以下错误。

I/flutter ( 3364): The following ProviderNotFoundException was thrown building AuthWrapper(dirty):
I/flutter ( 3364): Error: Could not find the correct Provider<AuthService> above this AuthWrapper Widget
I/flutter ( 3364):
I/flutter ( 3364): To fix, please:
I/flutter ( 3364):
I/flutter ( 3364):   * Ensure the Provider<AuthService> is an ancestor to this AuthWrapper Widget
I/flutter ( 3364):   * Provide types to Provider<AuthService>
I/flutter ( 3364):   * Provide types to Consumer<AuthService>
I/flutter ( 3364):   * Provide types to Provider.of<AuthService>()
I/flutter ( 3364):   * Ensure the correct `context` is being used.
I/flutter ( 3364):
I/flutter ( 3364): If none of these solutions work, please file a bug at:
I/flutter ( 3364): https://github.com/rrousselGit/provider/issues
I/flutter ( 3364):
I/flutter ( 3364): The relevant error-causing widget was:
[38;5;248mI/flutter ( 3364):   AuthWrapper[39;49m
I/flutter ( 3364):
I/flutter ( 3364): When the exception was thrown, this was the stack:
[38;5;248mI/flutter ( 3364): #0      Provider.of[39;49m
[38;5;248mI/flutter ( 3364): #1      AuthWrapper.build[39;49m
[38;5;244mI/flutter ( 3364): #2      StatelessElement.build[39;49m
[38;5;244mI/flutter ( 3364): #3      ComponentElement.performRebuild[39;49m
[38;5;244mI/flutter ( 3364): #4      Element.rebuild[39;49m
[38;5;244mI/flutter ( 3364): #5      ComponentElement._firstBuild[39;49m
[38;5;244mI/flutter ( 3364): #6      ComponentElement.mount[39;49m
[38;5;244mI/flutter ( 3364): #7      Element.inflateWidget[39;49m
[38;5;244mI/flutter ( 3364): #8      Element.updateChild[39;49m
[38;5;244mI/flutter ( 3364): #9      SingleChildRenderObjectElement.mount[3

我正在尝试provider 模式,这里到底发生了什么?

我还有第二个问题。好吧,provider 是一种模式。但是在颤振中,我们知道事情很少脱离上下文,这是否意味着所有业务逻辑(REST API 相关)都需要在 provider 中进行?或者,只在需要observer 模式行为的地方使用?

【问题讨论】:

在创建参数中你没有返回 AuthService(); .要么使用胖箭头函数,要么只在 AuthService(); 之前添加一个 return; 【参考方案1】:

我认为价值提供者可能是您案例的最佳解决方案。遵循最少的代码可以帮助您了解更多。

我认为这完全取决于您,如果您认为数据不是那么大,那么您可以避免使用提供程序,因为它会创建很多其他样板代码。不过我也建议你使用 flutter_bloc 包。

void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return StreamProvider<User>.value(
      value: AuthService().user,
      child: MaterialApp(
        home: FireBaseWrapper(),
      ),
    );
  



class FireBaseWrapper extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final _user = Provider.of<User>(context);
    print(_user);
    if (_user != null)
      return FireBase();
    else
      return Register();
  


    class AuthService 
  final FirebaseAuth _auth = FirebaseAuth.instance;
  User firebaseUserToUser(FirebaseUser _user) 
    return _user != null ? User(userId: _user.uid) : null;
  

  //stream of User
  Stream<User> get user 
    return _auth.onAuthStateChanged.map(firebaseUserToUser);
  

  // firebase sign in Anonymously
  Future signInAnonymously() async 
    try 
      AuthResult _authResult = await _auth.signInAnonymously();
      FirebaseUser _user = _authResult.user;
      return firebaseUserToUser(_user);
     catch (e) 
      return null;
    
  

  Future signInWithIdPassword(String email, String password) async 
    try 
      AuthResult _authResult = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
      FirebaseUser _user = _authResult.user;
      return firebaseUserToUser(_user);
     catch (e) 
      return null;
    
  

  Future signUpWithIdPassword(String email, String password) async 
    try 
      AuthResult _authResult = await _auth.createUserWithEmailAndPassword(
          email: email.trim(), password: password);
      FirebaseUser _user = _authResult.user;
      return firebaseUserToUser(_user);
     catch (e) 
      return null;
    
  

  // sign out
  Future signOut() async 
    try 
      return await _auth.signOut();
     catch (e) 
      return null;
    
  

【讨论】:

以上是关于颤振:找不到正确的提供者的主要内容,如果未能解决你的问题,请参考以下文章

Flutter cubit blocprovider 找不到正确的提供者

使用提供者值颤振初始路由

寻找提供者上下文的颤振问题

找不到正确的提供者不一致的行为

找不到正确的提供者<>

找不到提供者。它可能没有正确安装:ADODB [重复]