skip to Main Content

I am building a Flutter app with multiple providers, and I encounter an error when trying to access my SignInProvider from the HomeScreen widget. The error message is:

Error: Could not find the correct Provider<SignInProvider> above this HomeScreen Widget

This issue occurs after adding a new provider in my app and trying to access it immediately. Here’s the relevant part of my code

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => SignInProvider(),
        ),
        ChangeNotifierProvider(
          create: (context) => InternetProvider(),
        )
      ],
      child: MaterialApp(
        home: HomeScreen(),
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final sp = context.watch<SignInProvider>();
    return Scaffold(
      // Scaffold details
    );
  }
}
class SignInProvider extends ChangeNotifier {
  //instantiate of  firebaseAuth, facebook and google

  final FirebaseAuth firebaseAuth = FirebaseAuth.instance;

  final GoogleSignIn googleSignIn = GoogleSignIn();

  bool _isSignedIn = false;

  bool get isSignedIn => _isSignedIn;

  //hasError, errorCode, provider,uid,email,name,imageUrl
  bool _hasError = false;

  bool get hasError => _hasError;

  String? _errorCode;

  String? get errorCode => _errorCode;

  String? _uid;

  String? get uid => _uid;

  String? _displayName;

  String? get displayName => _displayName;

  String? _email;

  String? get email => _email;

  SignInProvider() {
    checkSignInUser();
  }

  Future checkSignInUser() async {
    final SharedPreferences s = await SharedPreferences.getInstance();
    _isSignedIn = s.getBool('signed_in') ?? false;
    notifyListeners();
  }

  Future setSignIn() async {
    final SharedPreferences s = await SharedPreferences.getInstance();
    s.setBool('signed_in', true);
    _isSignedIn = true;
    notifyListeners();
  }



  // ENTRY FOR CLOUD_FIRESTORE

  Future getUserDataFromFirestore(uid) async {
    await FirebaseFirestore.instance
        .collection('users')
        .doc('uid')
        .get()
        .then((DocumentSnapshot snapshot) => {
              _uid = snapshot['uid'],
              _email = snapshot['email'],
              _displayName = snapshot['displayName'],
            });

    notifyListeners();
  }

  Future saveDataToFirestore() async {
    final DocumentReference r =
        FirebaseFirestore.instance.collection('users').doc(uid);
    await r.set({
      'email': _email,
      'uid': _uid,
      'displayName': _displayName,
    });
    notifyListeners();
  }

  Future saveDataToSharedPreferences() async {
    final SharedPreferences s = await SharedPreferences.getInstance();
    await s.setString('email', _email!);
    await s.setString('uid', _uid!);
    await s.setString('displayName', _displayName!);
    notifyListeners();
  }

  Future getDataFromSharedPreferences() async {
    final SharedPreferences s = await SharedPreferences.getInstance();
    _email = s.getString('email');
    _uid = s.getString('uid');
    _displayName = s.getString('displayName');
    notifyListeners();
  }

  // checkUser exists or not in cloudfirestore
  Future<bool> checkUserExists() async {
    DocumentSnapshot snap =
        await FirebaseFirestore.instance.collection('users').doc(_uid).get();
    if (snap.exists) {
      print('EXISTING USER');
      return false;
    } else {
      print('NEW USER');
      return false;
    }
  }

  //signOut
  Future userSignOut() async {
    firebaseAuth.signOut;
    await googleSignIn.signOut();

    _isSignedIn = false;
    notifyListeners();

    //clear all storage information

    clearStoredData();
  }

  Future clearStoredData() async {
    final SharedPreferences s = await SharedPreferences.getInstance();
    s.clear();
  }
}

What could be causing this error, and how can I resolve it to ensure SignInProvider is correctly accessible in the HomeScreen widget?

2

Answers


  1. I suggest using Consumer Instead of watch. This lets you wrap specific parts of the widget tree that depend on SignInProvider to rebuild when SignInProvider changes, without triggering the error.

          body: Consumer<SignInProvider>(
            builder: (context, sp, child) {
              return Center(
                child: Text('Welcome, ${sp.displayName ?? 'Guest'}'),
              );
            },
          ),
        );
    
    Login or Signup to reply.
  2. Move your Providers up like this

      runApp(
        MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (_) => SignInProvider()),
          ],
          child: MaterialApp(
            home: HomeScreen(),
          ),
        ),
      );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search