ERROR: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following ProviderNotFoundException was thrown building AuthPage(dirty, state: _AuthPageState#7ac1c): Error: Could not find the correct Provider above this AuthPage Widget
This happens because you used a BuildContext
that does not include the provider
of your choice. There are a few common scenarios:
You added a new provider in your
main.dart
and performed a hot-reload. To fix, perform a hot-restart.The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then other routes will not be able to access that provider.
You used a
BuildContext
that is an ancestor of the provider you are trying to read.Make sure that AuthPage is under your MultiProvider/Provider. This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // Will throw a ProviderNotFoundError, because `context` is associated // to the widget that is the parent of `Provider<Example>` child: Text(context.watch<Example>()), ), }
consider using
builder
like so:Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // we use `builder` to obtain a new `BuildContext` that has access to the provider builder: (context) { // No longer throws return Text(context.watch<Example>()), } ), }
My Code:
AuthPage.dart:-
import 'package:first_app/pages/auth/bloc/auth_state.dart';
import 'package:first_app/pages/auth/widgets/auth_button.dart';
import 'package:first_app/pages/auth/widgets/otp_page.dart';
import 'package:first_app/pages/auth/widgets/phone_page.dart';
import 'package:first_app/pages/auth/widgets/set_up_account.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
class AuthPage extends StatefulWidget {
final int page;
final String? uid;
const AuthPage({
Key? key,
this.page = 0,
this.uid,
}) : super(key: key);
@override
_AuthPageState createState() => _AuthPageState();
}
class _AuthPageState extends State<AuthPage> {
@override
Widget build(BuildContext context) {
final state = Provider.of<AuthState>(context);
final screenSize = MediaQuery.of(context).size;
return
Builder(builder: (context) {
return Stack(
children: [
Container(
height: screenSize.height,
width: screenSize.width,
color: Colors.white,
child: PageView(
controller: state.controller,
onPageChanged: state.onPageChanged,
physics: NeverScrollableScrollPhysics(),
children: [
PhonePage(),
OtpPage(),
SetUpAccount(),
],
),
),
AuthButton(),
],
);
});
}
}
class AuthPageWidget extends StatelessWidget {
final int page;
final String? uid;
const AuthPageWidget({
Key? key,
required this.page,
this.uid,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final state = AuthState(page, uid ?? '');
return ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
);
}
}
AuthState.dart
import 'dart:async';
import 'package:first_app/models/user.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/services/auth.dart';
import 'package:first_app/services/map_services.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
enum PhoneAuthState { initial, success, loading, codeSent, error }
/*part of 'auth_bloc.dart';
abstract class AuthState extends Equatable {
const AuthState();
@override
List<Object> get props => [];
}*/
class AuthState extends ChangeNotifier {
final authService = AuthService.instance;
final userRepo = UserRepository.instance;
PhoneAuthState _phoneAuthState = PhoneAuthState.initial;
String verificationId = '';
TextEditingController phoneController = TextEditingController();
TextEditingController otpController = TextEditingController();
TextEditingController firstNameController = TextEditingController();
TextEditingController lastNameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController licensePlateController = TextEditingController();
TextEditingController vehicleColorController = TextEditingController();
TextEditingController vehicleTypeController = TextEditingController();
TextEditingController vehicleManufacturersController = TextEditingController();
Roles role = Roles.passenger;
PageController? controller;
int pageIndex = 0;
String uid = '';
int timeOut = 30;
bool get isRoleDriver => role == Roles.driver;
AuthState(int page, String uid) {
this.uid = uid;
controller = PageController(initialPage: page);
pageIndex = page;
notifyListeners();
siginCurrentUser();
}
PhoneAuthState get phoneAuthState => _phoneAuthState;
set changeRoleState(int value) {
role = Roles.values[value];
notifyListeners();
}
set phoneAuthStateChange(PhoneAuthState phoneAuthState) {
_phoneAuthState = phoneAuthState;
notifyListeners();
}
void animateToNextPage(int page) {
controller!.animateToPage(page, duration: Duration(milliseconds: 400), curve: Curves.easeIn);
pageIndex = page;
notifyListeners();
}
void onPageChanged(int value) {
pageIndex = value;
notifyListeners();
}
Future<void> signUp() async {
phoneAuthStateChange = PhoneAuthState.loading;
final address = await MapService.instance?.getCurrentPosition();
try {
final user = User(
uid: uid,
isActive: true,
firstname: firstNameController.text,
lastname: lastNameController.text,
email: emailController.text,
createdAt: DateTime.now(),
isVerified: true,
licensePlate: licensePlateController.text,
phone: "234${phoneController.text}",
vehicleType: vehicleTypeController.text,
vehicleColor: vehicleColorController.text,
vehicleManufacturer: vehicleManufacturersController.text,
role: role,
latlng: address?.latLng,
);
await userRepo.setUpAccount(user);
phoneAuthStateChange = PhoneAuthState.success;
} on FirebaseException catch (e) {
print(e.message);
phoneAuthStateChange = PhoneAuthState.error;
}
}
Future<void> phoneNumberVerification(String phone) async {
await AuthService.instance!.verifyPhoneSendOtp(phone, completed: (credential) async {
if (credential.smsCode != null && credential.verificationId != null) {
verificationId = credential.verificationId ?? '';
notifyListeners();
await verifyAndLogin(credential.verificationId!, credential.smsCode!, phoneController.text);
}
}, failed: (error) {
phoneAuthStateChange = PhoneAuthState.error;
}, codeSent: (String id, int? token) {
verificationId = id;
notifyListeners();
phoneAuthStateChange = PhoneAuthState.codeSent;
codeSentEvent();
print('code sent $id');
}, codeAutoRetrievalTimeout: (id) {
verificationId = id;
notifyListeners();
phoneAuthStateChange = PhoneAuthState.codeSent;
animateToNextPage(1);
print('timeout $id');
});
animateToNextPage(1);
notifyListeners();
}
Future<void> verifyAndLogin(String verificationId, String smsCode, String phone) async {
phoneAuthStateChange = PhoneAuthState.loading;
final uid = await authService?.verifyAndLogin(verificationId, smsCode, phone);
await userRepo.getUser(uid);
this.uid = uid ?? '';
animateToNextPage(2);
notifyListeners();
phoneAuthStateChange = PhoneAuthState.success;
print('completed');
}
Future<void> siginCurrentUser() async {
await userRepo.signInCurrentUser();
}
Future<void> codeSentEvent() async {
animateToNextPage(1);
_startCountDown();
}
void _startCountDown() {
Timer.periodic(Duration(seconds: 1), (timer) {
if (timer.tick > 30) {
timer.cancel();
} else {
--timeOut;
}
notifyListeners();
});
}
}
main.dart
import 'package:first_app/pages/home/home.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/ui/theme.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
UserRepository.instance.signInCurrentUser();
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BrilliantDrive',
theme: CityTheme.theme,
home: HomePage(),
);
}
}
CodePudding user response:
Initialize your provider 1st. Refer this https://stackoverflow.com/a/68418866/16467763.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<AuthState>(
create: (context) => AuthState(),
),
],
child: MyApp(),
),
);
}
CodePudding user response:
class AuthPageWidget extends StatelessWidget {
final int page;
final String? uid;
const AuthPageWidget({
Key? key,
required this.page,
this.uid,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final state = AuthState(page, uid ?? '');
return ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
);
}
}
You should move the ChangeNotifierProvider to your main.dart like this
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final state = AuthState(page, uid ?? '');
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (_) => state,
child: AuthPage(page: page, uid: uid),
),
),
);
}
OR
class SomeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
)
),
);
}
}