Флаттер: не удалось найти правильного провайдера - PullRequest
0 голосов
/ 20 февраля 2020

Я пытаюсь реализовать Firebase Authentication в моем приложении flutter с помощью provider. Во-первых, я проверяю, вошел ли пользователь в систему, если да, я отправляю его на экран home . Иначе я отправляю его на экран Логин .

Пожалуйста, проверьте мой код ниже.

main.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 это шаблон. Но во флаттере мы знаем, что вещи выходят за рамки контекста, значит ли это, что все бизнес-логики c (связанные с REST API) должны происходить в provider? Или же использовать только в тех местах, где вам нужно поведение observer?

1 Ответ

0 голосов
/ 20 февраля 2020

Я думаю, что поставщик стоимости может быть лучшим решением для вашего случая. Следующий минимальный код поможет вам понять больше.

Я думаю, что это полностью зависит от вас, если вы думаете, что данные не так уж велики, вы можете избежать использования провайдера, поскольку он создает много другого стандартного кода. Однако я также предлагаю вам использовать пакет flutter_blo c.

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;
    }
  }
}
...