context.watch<User?>() always returns null - flutter

When I try to use final firebaseUser = context.watch<User?>(), the value of firebaseUser is always null when I try to hot restart the application. And the after login IN (Email verified User) to application, the adminScreen is not build. I have used StreamProvider.
Main.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:heath_matthews_physio/screens/LogoutScreen.dart';
import 'package:heath_matthews_physio/screens/excercise.dart';
import 'package:heath_matthews_physio/screens/programsMy.dart';
import 'package:heath_matthews_physio/screens/AdminScreen.dart';
import 'package:heath_matthews_physio/screens/excerciseScreen.dart';
import 'package:heath_matthews_physio/screens/information_screen.dart';
import 'package:heath_matthews_physio/screens/login.dart';
import 'package:heath_matthews_physio/screens/mainScreen2.dart';
import 'package:heath_matthews_physio/screens/main_screen.dart';
import 'package:heath_matthews_physio/screens/myPrograms.dart';
import 'package:heath_matthews_physio/screens/reg_name_and_dp.dart';
import 'package:heath_matthews_physio/screens/register.dart';
import 'package:heath_matthews_physio/screens/verificationPage.dart';
import 'package:heath_matthews_physio/screens/workout-page.dart';
import 'package:heath_matthews_physio/screens/workoutScreen.dart';
import 'package:heath_matthews_physio/services/firebase_auth_methods.dart';
import 'package:heath_matthews_physio/wrapper.dart';
import 'package:provider/provider.dart';
import 'firebase_options.dart';
import 'screens/splash_screen.dart';
import 'package:firebase_core/firebase_core.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(
MaterialApp(
home: MyApp(),
debugShowCheckedModeBanner: false,
),
);
}
final navigatorKey = GlobalKey<NavigatorState>();
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<FirebaseAuthMethods>(
create: (_) => FirebaseAuthMethods(FirebaseAuth.instance),
),
StreamProvider(
create: (context) => context.read<FirebaseAuthMethods>().authState,
initialData: Null,
),
],
child: GetMaterialApp(
navigatorKey: navigatorKey,
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => const Splash(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/wrapper': (context) => wrapper(),
'/mainScreen': (context) => const mainScreen(),
'/mainScreen2': (context) => const mainScreen2(),
'/loginScreen': (context) => const Login(),
'/registerScreen': (context) => const Register(),
'/informationScreen': (context) => const informationScreen(),
'/mainScreen2': (context) => const mainScreen2(),
'/reg_name_and_dp': (context) => reg_name_and_dp(),
'/myPrograms': (context) => const myPrograms(),
'/adminScreen': (context) => adminScreen(),
'/program': (context) => program(),
'/workout-page': (context) => workoutScreen(),
// '/exerciseScreen':(context)=>excerciseScreen(),
'/exercise': (context) => exercise(),
'/workoutScreen': (context) => workoutScreen1(),
'/logout': (context) => logoutScreen(),
'/verification': (context) => verificationPage(),
},
theme: ThemeData(
primarySwatch: Colors.blue,
accentColor: Color(0xFF193669),
),
),
);
}
}
splash_screen.dart
import 'package:flutter/material.dart';
import 'package:heath_matthews_physio/DynamicSize/size.dart';
class Splash extends StatefulWidget {
const Splash({Key? key}) : super(key: key);
#override
_SplashState createState() => _SplashState();
}
class _SplashState extends State<Splash> {
#override
void initState() {
super.initState();
_navigateTologin();
}
_navigateTologin() async {
await Future.delayed(Duration(milliseconds: 1500), () {});
// Navigator.pushReplacementNamed(context, '/mainScreen');
Navigator.pushReplacementNamed(context, '/wrapper');
}
#override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color.fromARGB(178, 25, 54, 105),
Colors.white,
Color(0xFFEDC152)
])),
child: Padding(
padding: EdgeInsets.all(DynamicSize.Aaheight(78.0)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset("images/HMP LOGO.png"),
],
),
),
);
}
}
wrapper.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'screens/AdminScreen.dart';
import 'screens/main_screen.dart';
class wrapper extends StatelessWidget {
const wrapper({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User?>();
print("User : ${firebaseUser}"); //This always print null
if (firebaseUser != null) {
return adminScreen();
} else {
return mainScreen();
}
}
}
firebase_auth_methods.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:heath_matthews_physio/screens/register.dart';
class FirebaseAuthMethods {
final FirebaseAuth _auth;
FirebaseAuthMethods(this._auth);
//State Management
Stream<User?> get authState => _auth.idTokenChanges();
//Email Sign Up Function
Future<void> singUpWithEmail({
required String email,
required String password,
required BuildContext context,
}) async {
try {
await _auth.createUserWithEmailAndPassword(
email: email, password: password);
await sendVerification(context);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
//Email LogIn Function
Future<void> signInWithEmail(
{required String email,
required String password,
required BuildContext context}) async {
try {
await _auth.signInWithEmailAndPassword(email: email, password: password);
if (!_auth.currentUser!.emailVerified) {
await sendVerification(context);
}
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
//Send Email Verification
Future<void> sendVerification(BuildContext context) async {
try {
_auth.currentUser!.sendEmailVerification();
popUpVerificationMsg(context);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
}
login.dart
import 'package:flutter/material.dart';
// import 'package:dotted_line/dotted_line.dart';
import 'package:heath_matthews_physio/DynamicSize/size.dart';
import 'package:heath_matthews_physio/services/firebase_auth_methods.dart';
import 'package:provider/provider.dart';
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
#override
State<Login> createState() => _LoginState();
}
class _LoginState extends State<Login> {
final emailController = TextEditingController();
final passwordController = TextEditingController();
#override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
//To Control PassWord Visibiltiy
late bool _visibility;
Future popUpConfirm(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(DynamicSize.Faheight(16))),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(
left: DynamicSize.Fawidth(31),
top: DynamicSize.Faheight(24),
right: DynamicSize.Fawidth(31)),
child: Image.asset('images/EmailSent.png'),
),
//Msg
SizedBox(height: DynamicSize.Faheight(24)),
Padding(
padding: EdgeInsets.only(
left: DynamicSize.Fawidth(16),
right: DynamicSize.Fawidth(16),
bottom: DynamicSize.Faheight(32)),
child: Text(
"You will receive an email with intructions on how to reset your password in a few minutes.\n\nNote : Don't forget to check your spam mail box.\n\nThank you :)",
style: TextStyle(
fontFamily: 'DMSans',
fontSize: DynamicSize.Faheight(16),
fontWeight: FontWeight.w400,
letterSpacing: DynamicSize.Fawidth(0.5),
color: Color(0xFF193669),
fontStyle: FontStyle.normal,
),
),
)
],
),
);
},
);
}
Future popUpDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(DynamicSize.Faheight(16))),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(
left: DynamicSize.Fawidth(31),
top: DynamicSize.Faheight(16),
right: DynamicSize.Fawidth(31)),
child: Image.asset('images/Illustration-forgot-password.png'),
),
//Forgot password Text
SizedBox(height: DynamicSize.Faheight(24)),
Padding(
padding: EdgeInsets.only(left: DynamicSize.Fawidth(24)),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'Forgot your password?',
style: TextStyle(
fontStyle: FontStyle.normal,
color: Color(0xFF193669),
fontFamily: 'DMSans',
fontSize: DynamicSize.Faheight(16),
fontWeight: FontWeight.w500,
letterSpacing: DynamicSize.Fawidth(1),
),
),
),
),
//Email Text
SizedBox(height: DynamicSize.Faheight(36)),
Padding(
padding: EdgeInsets.only(left: DynamicSize.Fawidth(24)),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'Email',
style: TextStyle(
fontStyle: FontStyle.normal,
color: Color(0xFF193669),
fontFamily: 'DMSans',
fontSize: DynamicSize.Faheight(12),
fontWeight: FontWeight.w700,
letterSpacing: DynamicSize.Fawidth(1),
),
),
),
),
//Email TextField
SizedBox(height: DynamicSize.Faheight(9)),
Padding(
padding:
EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(24)),
child: TextField(
decoration: InputDecoration(
hintText: 'Email address',
hintStyle: TextStyle(
color: Color(0xFF636363),
),
focusedBorder: new UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF193669)),
),
),
keyboardType: TextInputType.emailAddress,
),
),
//Button
SizedBox(height: DynamicSize.Faheight(24)),
Padding(
padding:
EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(24)),
child: SizedBox(
width: double.infinity,
height: DynamicSize.Faheight(39),
child: OutlinedButton(
onPressed: () {
Navigator.pop(context);
popUpConfirm(context);
},
style: OutlinedButton.styleFrom(
side: BorderSide(
color: Color(0xFF193669),
),
backgroundColor: Color(0xFFF0F2F4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
DynamicSize.Faheight(15))),
),
child: Text(
'Send me reset password instructions',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'DMSans',
fontStyle: FontStyle.normal,
fontWeight: FontWeight.w500,
fontSize: DynamicSize.Faheight(11),
letterSpacing: DynamicSize.Fawidth(0.8),
color: Color(0xFF193669),
),
),
),
),
),
SizedBox(height: DynamicSize.Faheight(30)),
],
),
),
);
},
);
}
#override
void initState() {
super.initState();
_visibility = false;
}
void LoginUser() {
context.read<FirebaseAuthMethods>().signInWithEmail(
email: emailController.text.trim(),
password: passwordController.text.trim(),
context: context);
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//Grettings
SizedBox(height: DynamicSize.Faheight(150)),
Container(
child: Text(
"Welcome Back",
style: TextStyle(
fontFamily: 'DMSams',
fontSize: DynamicSize.Faheight(30),
fontWeight: FontWeight.w700,
color: Color(0xff193669),
letterSpacing: DynamicSize.Fawidth(0.5),
),
),
),
SizedBox(height: DynamicSize.Faheight(17)),
Container(
margin: EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(17)),
child: Text(
'Hey, nice seeing you again !! Please login/register to continue further',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'DMSans',
fontSize: DynamicSize.Faheight(14),
fontWeight: FontWeight.w600,
color: Color(0xff193669),
letterSpacing: DynamicSize.Fawidth(0.5),
),
),
),
//User Credentials
SizedBox(height: DynamicSize.Faheight(60)),
Container(
padding: EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(19)),
margin: EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(25)),
alignment: Alignment.center,
height: DynamicSize.Faheight(50),
decoration: BoxDecoration(
color: Color(0xFFF3F3F3),
borderRadius: BorderRadius.circular(DynamicSize.Faheight(15)),
boxShadow: [
BoxShadow(
offset: Offset(0, DynamicSize.Faheight(2)),
color: Color.fromARGB(141, 0, 0, 0),
blurRadius: DynamicSize.Faheight(3),
),
BoxShadow(
offset: Offset(DynamicSize.Fawidth(-2), 0),
color: Color(0xFFF3F3F3),
blurRadius: DynamicSize.Faheight(1),
),
BoxShadow(
offset: Offset(DynamicSize.Fawidth(2), 0),
color: Color(0xFFF3F3F3),
blurRadius: DynamicSize.Faheight(1),
),
],
),
child: TextField(
controller: emailController,
style: TextStyle(
fontFamily: 'DMSams',
fontSize: DynamicSize.Faheight(14),
letterSpacing: DynamicSize.Fawidth(0),
),
decoration: InputDecoration(
hintText: "Email address",
border: InputBorder.none,
),
keyboardType: TextInputType.emailAddress,
),
),
//Password field
SizedBox(height: DynamicSize.Faheight(15)),
Container(
padding: EdgeInsets.only(
left: DynamicSize.Fawidth(19), right: DynamicSize.Fawidth(8)),
margin: EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(25)),
alignment: Alignment.center,
height: DynamicSize.Faheight(50),
decoration: BoxDecoration(
color: Color(0xFFF3F3F3),
borderRadius: BorderRadius.circular(DynamicSize.Faheight(15)),
boxShadow: [
BoxShadow(
offset: Offset(0, DynamicSize.Faheight(2)),
color: Color.fromARGB(141, 0, 0, 0),
blurRadius: DynamicSize.Faheight(3),
),
BoxShadow(
offset: Offset(DynamicSize.Fawidth(-2), 0),
color: Color(0xFFF3F3F3),
blurRadius: DynamicSize.Faheight(1),
),
BoxShadow(
offset: Offset(DynamicSize.Fawidth(2), 0),
color: Color(0xFFF3F3F3),
blurRadius: DynamicSize.Faheight(1),
),
],
),
child: TextField(
controller: passwordController,
textAlignVertical: TextAlignVertical.center,
style: TextStyle(
fontFamily: 'DMSams',
fontSize: DynamicSize.Faheight(14),
letterSpacing: DynamicSize.Fawidth(0),
),
decoration: InputDecoration(
hintText: "Password",
border: InputBorder.none,
suffixIcon: IconButton(
splashRadius: 1,
splashColor: Colors.transparent,
icon: Icon(
_visibility ? Icons.visibility_off : Icons.visibility),
color: Color(_visibility ? (0xFF193669) : (0xFF666161)),
onPressed: () => setState(() => _visibility = !_visibility),
),
),
obscureText: !_visibility,
),
),
//Forgot Password Button
SizedBox(height: DynamicSize.Faheight(13)),
Container(
padding: EdgeInsets.only(right: DynamicSize.Fawidth(36)),
alignment: Alignment.topRight,
child: GestureDetector(
onTap: () => popUpDialog(context),
child: Text(
"Forgot Password ?",
style: TextStyle(
fontFamily: "DMSans",
fontSize: DynamicSize.Faheight(15),
color: Color(0xFF193669),
),
),
),
),
//Sign In Button
SizedBox(height: DynamicSize.Faheight(40)),
Padding(
padding: EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(15)),
child: SizedBox(
width: double.infinity,
height: DynamicSize.Faheight(50),
child: TextButton(
onPressed: LoginUser,
// Navigator.pushNamedAndRemoveUntil(
// context, '/adminScreen', (route) => false),
style: TextButton.styleFrom(
backgroundColor: Color(0xFF193669),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(DynamicSize.Faheight(15)),
)
// padding: EdgeInsets.symmetric(horizontal: 1),
),
child: Text(
'SIGN IN',
style: TextStyle(
fontFamily: 'DMSans',
fontSize: DynamicSize.Faheight(15),
letterSpacing: DynamicSize.Fawidth(0.5),
color: Colors.white,
),
),
),
),
),
//Register Button
SizedBox(height: DynamicSize.Faheight(16)),
Padding(
padding: EdgeInsets.symmetric(horizontal: DynamicSize.Fawidth(15)),
child: SizedBox(
width: double.infinity,
height: DynamicSize.Faheight(50),
child: TextButton(
onPressed: () =>
Navigator.pushNamed(context, '/registerScreen'),
style: TextButton.styleFrom(
backgroundColor: Color(0xFF193669),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(DynamicSize.Faheight(15)),
)
// padding: EdgeInsets.symmetric(horizontal: 1),
),
child: Text(
'REGISTER',
style: TextStyle(
fontFamily: 'DMSans',
fontSize: DynamicSize.Faheight(15),
letterSpacing: DynamicSize.Fawidth(0.5),
color: Colors.white,
),
),
),
),
),
// Row(
// children: [
// Text("No Account?",style: GoogleFonts.dmSans(
// fontSize: 12.0,
// color: Color(0xFF2F3F70)
// ),),
// Text("Sign Up",style: TextStyle(
// fontSize:12.0,
// fontWeight: FontWeight.w500,
// decoration: TextDecoration.underline,
// fontFamily: 'dmSams'
// ),
// )
// ],
// )
],
),
);
}
}

Related

MaterialPageRoute (The named parameter 'key' is required, but there's no corresponding argument)

i'm trying 2 Navigate to a new screen and back like this in register_email.dart
=>push
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WelcomePage()),
);
=>pop
Navigator.pop(
context,
MaterialPageRoute(
builder: (context) => LoginPage(),
),
but it won't work for me on WelcomePage()) showing this
errors
:
The named parameter 'key' is required, but there's no corresponding
argument. Try adding the required argument
register_email.dart:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:imibonano/pages/loginPhone/welcome_page.dart';
import 'package:imibonano/theme/colors.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/foundation/key.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:validators/validators.dart';
class EmailRegisterPage extends StatefulWidget {
const EmailRegisterPage({key}) : super(key: key);
#override
State<EmailRegisterPage> createState() => _EmailRegisterPageState();
}
class _EmailRegisterPageState extends State<EmailRegisterPage> {
#override
final _formKey = GlobalKey<FormState>();
TextEditingController _email = TextEditingController();
Widget build(BuildContext context) {
return Scaffold(
appBar: getAppbar(),
body: getBody(),
);
}
Widget getBody() {
return ListView(
children: [
Column(
children: [
Container(
margin: const EdgeInsets.only(left: 15.0, right: 8.0),
// color: Colors.blue,
padding: const EdgeInsets.only(left: 25, top: 30),
width: 350,
child: Text(
"Email của bạn là gì ",
style: TextStyle(
color: black,
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
),
Container(
margin: EdgeInsets.only(left: 10, right: 20, top: 40),
padding: EdgeInsets.only(left: 30, right: 30),
child: Text(
"Hãy xác minh email của bạn để không bị mất quyền truy cập vào tài khoản",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
),
Container(
margin: EdgeInsets.only(right: 40, top: 20, left: 40),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _email,
decoration: InputDecoration(
hintText: "Nhập Email",
),
validator: (value) {
if (value != null) {
if (value.length > 5 &&
value.contains('#') &&
value.endsWith('.com')) {
return null;
}
return 'Enter a Valid Email Address';
}
},
),
],
),
),
),
SizedBox(
height: 50,
),
InkWell(
borderRadius: BorderRadius.circular(60),
onTap: (() async {
// if (!_formKey.currentState.validate()) {
// FirebaseAuth.instance.currentUser?.uo(_text.text);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WelcomePage()),
);
User? user = FirebaseAuth.instance.currentUser;
await FirebaseFirestore.instance
.collection('user')
.doc(user!.uid)
.update({
'email': _email.text,
});
// } else {
// return;
// }
}),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(60),
color: Color.fromARGB(255, 255, 25, 75),
),
width: 320,
height: 50,
child: Center(
child: Text(
"TIẾP TỤC",
style: TextStyle(
fontWeight: FontWeight.w500,
),
),
),
),
),
],
),
],
);
}
AppBar getAppbar() {
return AppBar(
elevation: 0,
backgroundColor: white,
iconTheme: IconThemeData(
color: black,
),
);
}
}
what I'm missing, where parameter 'key' is required ?
The key is optional. So, need to define optional keyword Key?
class EmailRegisterPage extends StatefulWidget {
const EmailRegisterPage({Key? key}) : super(key: key);
#override
State<EmailRegisterPage> createState() => _EmailRegisterPageState();
}
And to POP
Navigator.pop(context);
Navigator.pop(context);
Navigator.pop doesn't need the material page route again to pop the current screen
More about Navigator
use this code to Navigate to a new screen from the login screen.
Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => WelcomePage()));

Move Textfield up when Keyboard apperears inside Bottom Sheet in Flutter

I am currently trying to create some kind of TikTok like comment section in flutter. For this I'm using a ModalBottomSheet and a Expanded Listview with the comments inside. However, I'm failing to archive that my TextField moves up when its selected and the Keyboard appears, meaning I always cant see the Textfield anymore after it's selection. I already tried using a focusnode and animation controller, however it didnt work out because of the Flex container which contains the comments... I know it's much code but please help I really cant figure it out.
The BottomSheet Widget:
void onCommentButtonPressed() {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => Container(
height: MediaQuery.of(context).size.height * 0.75,
decoration: new BoxDecoration(
color: Colors.grey[900],
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(20.0),
topRight: const Radius.circular(20.0),
),
),
child: Column(
children: <Widget>[
Comments(
postId: targetId,
postOwnerId: ownerId,
),
],
),
),
);
}
and the comment section inside of it:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/Widgets/Images/profile_picture_small.dart';
import 'package:flutter_app/Widgets/header.dart';
import 'package:flutter_app/Widgets/progress.dart';
import 'package:flutter_app/constants.dart';
import 'package:provider/provider.dart';
import '../../Screens/Authenticate/authservice.dart';
import '../../Screens/Authenticate/database.dart';
import '../../models/user.dart';
import 'package:timeago/timeago.dart' as timeago;
class Comments extends StatefulWidget {
final String postId;
final String postOwnerId;
Comments({
required this.postId,
required this.postOwnerId,
});
#override
CommentsState createState() => CommentsState(
postId: postId,
postOwnerId: postOwnerId,
);
}
class CommentsState extends State<Comments> {
TextEditingController commentController = TextEditingController();
final String postId;
final String postOwnerId;
CommentsState({
required this.postId,
required this.postOwnerId,
});
#override
Widget build(BuildContext context) {
return Flexible(
child: Column(
children: [
Expanded(
child: buildComments(),
),
buildTextField(),
],
),
);
}
addComment(){
final currentUser = Provider.of<MyUser>(context, listen: false);
bool isNotPostOwner = postOwnerId != currentUser.id;
commentsRef.doc(postId).collection('comments').add({
'username': currentUser.username,
'comment': commentController.text,
'timestamp': DateTime.now(),
'avatarUrl': currentUser.photoUrl,
'userId': currentUser.id,
});
if(isNotPostOwner) {
activityFeedRef.doc(postOwnerId).collection('feedItems').add({
'type': 'comment',
'commentData': commentController.text,
'username': currentUser.username,
'userId': currentUser.id,
'userProfileImg': currentUser.photoUrl,
'postId': postId,
'timestamp': timestamp,
});
}
commentController.clear();
}
buildComments() {
return StreamBuilder<QuerySnapshot>(
stream: commentsRef.
doc(postId).
collection('comments').
orderBy('timestamp', descending: true).
snapshots(),
builder: (context, snapshot){
if (!snapshot.hasData){
return circularProgress();
}
else {
List<Comment> comments = [];
snapshot.data!.docs.forEach((doc){
comments.add(Comment.fromDocument(doc));
});
return ListView(children: comments,);
}
},
);
}
Widget buildTextField() {
return Container(
padding: EdgeInsets.symmetric(
vertical: kDefaultPadding / 2,
horizontal: kDefaultPadding / 2,
),
decoration: BoxDecoration(
color: Colors.transparent,
boxShadow: [
BoxShadow(
offset: Offset(0, 4),
blurRadius: 32,
color: Colors.blueGrey.withOpacity(0.1),
),
],
),
child: SafeArea(
child: Row(
children: [
ProfilePictureSmall(),
Padding(padding: EdgeInsets.symmetric(horizontal: 5)),
Expanded(
child: Container(
padding: EdgeInsets.symmetric(
horizontal: kDefaultPadding * 0.75,
),
decoration: BoxDecoration(
color: Colors.grey[800],
borderRadius: BorderRadius.circular(40),
),
child: Row(
children: [
SizedBox(width: kDefaultPadding / 4),
Expanded(
child: TextField(
controller: commentController,
decoration: InputDecoration(
hintText: "Write a comment...",
border: InputBorder.none,
),
),
),
InkWell(
onTap: () => addComment(),
child: Container(
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(40.0),
),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Icon(
Icons.arrow_upward_rounded,
color: Theme.of(context)
.textTheme
.bodyText1!
.color!
.withOpacity(0.64),
),
),
),
),
],
),
),
),
],
),
),
);
}
}
class Comment extends StatelessWidget {
final String username;
final String userId;
final String avatarUrl;
final String comment;
final Timestamp timestamp;
Comment({
required this.username,
required this.userId,
required this.avatarUrl,
required this.comment,
required this.timestamp,
});
factory Comment.fromDocument(DocumentSnapshot doc){
return Comment(
username: doc['username'],
userId: doc['userId'],
comment: doc['comment'],
timestamp: doc['timestamp'],
avatarUrl: doc['avatarUrl'],
);
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ListTile(
title: RichText(
text: TextSpan(text: '#...$username ',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
children: <TextSpan> [
TextSpan(text: '$comment',
style: Theme.of(context).textTheme.bodyText2),
]
),
),
leading: ProfilePictureSmall(),
subtitle: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 12,
color: Colors.white,
fontWeight: FontWeight.bold,
),
children: <TextSpan> [
TextSpan(text: '${timeago.format(timestamp.toDate(), locale: 'en_short')} ',
style: TextStyle(
color: Colors.grey[400],
fontWeight: FontWeight.w400,
),),
TextSpan(text: '193 Rockets ',
style: TextStyle(
color: Colors.grey[400]
),),
TextSpan(text: 'Reply',
style: TextStyle(
color: Colors.grey[400]
),
),
]
),
),
trailing: buildCommentFooter(context),
),
// Divider(color: Colors.white,),
],
);
}
buildCommentFooter(BuildContext context){
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: ()=> print('pressed'),
child: Icon(
Icons.monetization_on_rounded,
size: 20,
color: Colors.grey,
),
),
],
);
}
}

flutter - provider listen:false doesn't work

I'm using flutter to make an app
there is an error related with provider
I tried to write Provider.of<Category>(context, listen: false); to fix this error
but error keeps showing
how can I fix this error?
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:get/get.dart';
import 'result_screen.dart';
import 'package:youtube_ad2/provider/food_provider.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
InterstitialAd? interstitialAd;
bool isLoaded = false;
#override
void initState() {
super.initState();
Provider.of<Category>(context, listen: false);
}
#override
void didChangeDependencies() {
//TODO implement didChangeDependencies
super.didChangeDependencies();
InterstitialAd.load(
adUnitId: InterstitialAd.testAdUnitId,
request: AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (ad) {
setState(() {
isLoaded = true;
interstitialAd = ad;
});
print("Ad Loaded");
},
onAdFailedToLoad: (error) {
print("Interstitial Failed to load");
},
),
);
}
String? value;
List<String> listItem = ["전체", "중국", "한국", "일본", "동남아", "유럽", "아메리카"];
#override
Widget build(BuildContext context) {
return Container(
// decoration: BoxDecoration(
// image: DecorationImage(
// fit: BoxFit.cover,
// image: AssetImage('assets/images/bg3.png'), // 배경 이미지
// ),
// ),
child: Scaffold(
backgroundColor: Colors.orange[300],
appBar: AppBar(
automaticallyImplyLeading: false,
elevation: 0,
title: Center(
child: Text(
'오늘의 식사',
style: TextStyle(
fontFamily: 'Chilgok',
color: Colors.yellow.shade300,
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
ElevatedButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/logo.png',
width: MediaQuery.of(context).size.width / 3,
),
Text('Open!'),
]),
style: ElevatedButton.styleFrom(
side: BorderSide(
width: 5,
color: Colors.red,
),
elevation: 40,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100)),
primary: Colors.orange[300],
padding: const EdgeInsets.only(
top: 9,
bottom: 15,
left: 20,
right: 20,
),
),
onPressed: () {
if (isLoaded) {
interstitialAd!.show();
Provider.of<Category>(context, listen: false);
context
.read<FoodResult>()
.selectFood(context.read<Category>().category);
Get.to(() => ResultScreen());
} else {
Provider.of<Category>(context, listen: false);
context
.read<FoodResult>()
.selectFood(context.read<Category>().category);
Get.to(() => ResultScreen());
}
},
),
Container(
padding: EdgeInsets.only(
left: 10,
right: 10,
top: 3,
bottom: 5,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: Colors.red,
width: 4,
),
),
width: MediaQuery.of(context).size.width / 3,
height: 40,
child: DropdownButton<String>(
underline: DropdownButtonHideUnderline(child: Container()),
dropdownColor: Colors.grey[200],
borderRadius: BorderRadius.circular(10),
elevation: 0,
hint: Text(
"음식종류",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17,
),
),
value: value,
iconSize: 20,
icon: Icon(Icons.arrow_drop_down, color: Colors.red),
isExpanded: true,
items: listItem.map(valueItem).toList(),
onChanged: (value) => setState(() => this.value = value),
),
)
],
),
)),
);
}
DropdownMenuItem<String> valueItem(String item) => DropdownMenuItem(
value: item,
child: Text(
item,
style: TextStyle(
color: Colors.black87,
fontSize: 20,
),
),
);
}
try this code
#override void initState(){
Future.delayed(Duration.zero).then((_) =>
Provider.of<Category>(context, listen: false););
super.initState();
}

NoSuchMethod Error: Method called on null

//in this code i am tring to use connectivity. Android recommended me to add some classes, //getters setter, I added them at the end of the code automatically
import 'package:firebase_auth/firebase_auth.dart';[enter image description here][1]
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'signup.dart';
import 'home.dart';
import 'dart:async';
import 'dart:developer' as developer;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
#override
_LoginState createState() => _LoginState();
}
//loginstate
class _LoginState extends State<Login> {
ConnectivityResult? _connectionStatus = ConnectivityResult.none;
final Connectivity _connectivity = Connectivity();
late StreamSubscription<ConnectivityResult> _connectivitySubscription;
#override
void initState() {
super.initState();
initConnectivity();
_connectivitySubscription =
_connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
}
#override
void dispose() {
_connectivitySubscription.cancel();
super.dispose();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initConnectivity() async {
late ConnectivityResult result;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await _connectivity.checkConnectivity();
} on PlatformException catch (e) {
developer.log('Couldn\'t check connectivity status', error: e);
return;
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) {
return Future.value(null);
}
return _updateConnectionStatus(result);
}
Future<void> _updateConnectionStatus(ConnectivityResult result) async {
setState(() {
_connectionStatus = result;
});
}
//Login function
static Future<User?> loiginUsingEmailPassword(
{required String email,
required String password,
required BuildContext context}) async {
FirebaseAuth auth = FirebaseAuth.instance;
User? user;
try {
UserCredential userCredential = await auth.signInWithEmailAndPassword(
email: email, password: password);
user = userCredential.user;
} on FirebaseAuthException catch (e) {
if (e.code == "user-not-found") {
print("No user found for that email");
}
}
return user;
}
#override
Widget build(BuildContext context) {
//create textfield controller
TextEditingController _emailController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
return Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(15.0, 110.0, 0.0, 0.0),
child: Text(
'Bon Appétit',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 50.0,
),
),
),
//new container
Container(
padding: EdgeInsets.only(top: 35.0, left: 20.0, right: 20.0),
child: Column(
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFFcaa052)),
),
labelText: 'EMAIL',
labelStyle: TextStyle(
fontFamily: 'Alegreya Sans',
fontWeight: FontWeight.bold,
color: Color(0xFFcaa052),
),
),
),
SizedBox(
height: 20.0,
),
TextField(
controller: _passwordController,
decoration: InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFFcaa052)),
),
labelText: 'PASSWORD',
labelStyle: TextStyle(
fontFamily: 'Alegreya Sans',
fontWeight: FontWeight.bold,
color: Color(0xFFcaa052),
),
),
obscureText: true,
),
SizedBox(
height: 5.0,
),
Container(
alignment: Alignment(1.0, 0.0),
padding: EdgeInsets.only(top: 15.0, left: 20.0),
child: InkWell(
child: Text(
'Forgot Password',
style: TextStyle(
color: Color(0xFF5E0B0B),
fontWeight: FontWeight.bold,
fontFamily: 'Alegreya Sans',
decoration: TextDecoration.underline,
),
),
),
),
SizedBox(
height: 40.0,
),
],
),
),
SizedBox(
height: 15.0,
),
Container(
height: 40.0,
width: 400.0,
child: Material(
borderRadius: BorderRadius.circular(20.0),
shadowColor: Color(0xFFffffb1),
color: Color(0xFFffd180),
elevation: 7.0,
child: InkWell(
onTap: () async {
User? user = await loiginUsingEmailPassword(
email: _emailController.text,
password: _passwordController.text,
context: context);
print(user);
if (user != null) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Home()),
);
}
},
child: Center(
child: Text(
'LOGIN',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontFamily: 'Alegreya Sans',
),
),
),
),
),
),
Container(
child: Text('Connection Status: ${_connectionStatus.toString()}'),
),
SizedBox(
height: 15.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'New member?',
style: TextStyle(fontFamily: 'Alegreya Sans'),
),
SizedBox(
width: 5.0,
),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Signup()),
);
},
child: Text(
'Sign up',
style: TextStyle(
color: Color(0xFF5E0B0B),
fontWeight: FontWeight.bold,
fontFamily: 'Alegreya Sans',
decoration: TextDecoration.underline,
),
),
),
],
),
],
),
),
);
}
}
//i think because of below code i got error
class ConnectivityResult {
static ConnectivityResult? none;
}
class Connectivity {
get onConnectivityChanged => null;
checkConnectivity() {}
}

Why does a change in state of a child bottom sheet trigger a rebuild of parent widget?

I have a Scaffold screen (ListsScreen).
Which has a Button(AddNewListButton) that opens up a Modal Bottom Sheet (ListScreenBottomSheetWidget).
Bottom Sheet has TextField (ListTitleInputTextFieldWidget).
When i tap the TextField to open the keyboard, the parent screen rebuilds itself, due to which ofcourse all its child widgets are rebuilt as well.
Why is this happening? I was under the impression that state changes only rebuild themselves or their children, not their parents. And i also added const constructors almost everywhere to avoid rebuilds but this is still happening.
The Parent ListsScreen:
class ListsScreen extends StatelessWidget {
const ListsScreen();
static const routeName = '/lists-screen';
#override
Widget build(BuildContext context) {
final user = Provider.of<AuthProvider>(context, listen: false).getUser;
print('stateless rebuilding');
return Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text(
'${user['name']}\'s Lists',
style: TextStyle(
color: Theme.of(context).primaryColorLight,
),
),
actions: <Widget>[
const SignOutButton(),
],
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
SizeConfig.smallDevice
? const SizedBox(
height: 30,
)
: const SizedBox(
height: 40,
),
SizeConfig.smallDevice
? Text(
'Welcome to TODOS',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
color: Colors.grey[700],
),
)
: Text(
'Welcome to TODOS',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
color: Colors.grey[700],
),
),
SizeConfig.smallDevice
? const SizedBox(
height: 30,
)
: const SizedBox(
height: 40,
),
const AddNewListButton(),
SizeConfig.smallDevice
? const SizedBox(
height: 30,
)
: const SizedBox(
height: 40,
),
const UserListsListViewWidget(),
],
),
),
),
);
}
}
class SignOutButton extends StatelessWidget {
const SignOutButton();
Future<void> _submitRequest(BuildContext context) async {
_showLoadingAlert(context);
try {
await Provider.of<AuthProvider>(context, listen: false)
.submitLogOutRequest();
Navigator.of(context).pop();
Navigator.of(context).pushReplacementNamed(LoginScreen.routeName);
} on HttpExceptions catch (error) {
Navigator.of(context).pop();
_showErrorDialogue(error.getErrorList, context);
}
}
void _showErrorDialogue(List<dynamic> errorMessages, BuildContext context) {
showDialog(
context: context,
builder: (ctx) => Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: ErrorListWidget(errorMessages: errorMessages),
),
);
}
void _showLoadingAlert(BuildContext context) {
showDialog(
context: context,
builder: (ctx) => const LoadingWidget(),
);
}
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () => _submitRequest(context),
child: Row(
children: <Widget>[
Text(
'Sign Out',
style: TextStyle(
color: Theme.of(context).primaryColorLight,
),
),
Icon(
Icons.exit_to_app,
color: Theme.of(context).primaryColorLight,
),
],
),
);
}
}
class AddNewListButton extends StatelessWidget {
const AddNewListButton();
void _modalBottomSheetMenu(BuildContext context) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
isScrollControlled: true,
builder: (builder) {
return const ListScreenBottomSheetWidget();
},
);
}
#override
Widget build(BuildContext context) {
return RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 10,
color: Theme.of(context).primaryColor,
onPressed: () => _modalBottomSheetMenu(context),
child: Text(
'+ Add List',
style: TextStyle(
color: Colors.white,
fontSize: SizeConfig.smallDevice ? 10 : 15,
),
),
);
}
}
The Modal Bottom Sheet:
import 'package:flutter/material.dart';
import 'package:todo_spicotech/helpers/size_config.dart';
class ListScreenBottomSheetWidget extends StatelessWidget {
const ListScreenBottomSheetWidget();
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
currentFocus.unfocus();
},
child: Container(
margin: const EdgeInsets.all(20.0),
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Material(
borderRadius: BorderRadius.all(Radius.circular(15)),
elevation: 10,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizeConfig.smallDevice
? Text(
'Create a new List',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
color: Colors.grey[700],
),
)
: Text(
'Create a new List',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
color: Colors.grey[700],
),
),
SizeConfig.smallDevice
? const SizedBox(
height: 20,
)
: const SizedBox(
height: 30,
),
const ListTitleInputTextFieldWidget(),
SizeConfig.smallDevice
? const SizedBox(
height: 20,
)
: const SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(
borderRadius: BorderRadius.circular(5),
onTap: () {
Navigator.of(context).pop();
},
child: Ink(
padding: EdgeInsets.all(10),
child: const Text('CANCEL'),
),
),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 10,
color: Theme.of(context).primaryColor,
onPressed: () {},
child: Text(
'Create',
style: TextStyle(
color: Colors.white,
fontSize: SizeConfig.smallDevice ? 10 : 15,
),
),
),
],
),
],
),
),
),
),
);
}
}
class ListTitleInputTextFieldWidget extends StatefulWidget {
const ListTitleInputTextFieldWidget();
#override
_ListTitleInputTextFieldWidgetState createState() => _ListTitleInputTextFieldWidgetState();
}
class _ListTitleInputTextFieldWidgetState extends State<ListTitleInputTextFieldWidget> {
#override
Widget build(BuildContext context) {
return TextFormField(
decoration: const InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.lightBlue,
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.lightBlue,
),
),
labelText: 'List Title',
contentPadding: EdgeInsets.all(10),
),
);
}
}
when you call showModalBottomSheet , it actually use Navigator inside
return Navigator.of(context, rootNavigator: useRootNavigator).push(_ModalBottomSheetRoute<T>(
builder: builder,
source code of showModalBottomSheet https://github.com/flutter/flutter/blob/17079f26b54c8517678699a0cefe5f7bfec67b3f/packages/flutter/lib/src/material/bottom_sheet.dart#L635
Flutter teams' reply of issue Pages on Navigator stack rebuild when a new page is pushed https://github.com/flutter/flutter/issues/11655#issuecomment-348287396
This is working as intended. In general, you should assume that all widgets can rebuild at any time, that they don't is mostly just an optimisation.
In particular, routes will rebuild because their navigator state has changed so they might need to update how they draw back buttons and the like.