我有2个提供者。一个用于Firebase逻辑,另一个用于某些ui设计。我在Firebase
和Provider
上进行登录时遇到问题。问题是,当我登录Firebase用户notifylisteners()
时使用“ (Status.Authenticated)
”时,根页面没有更新,即使单击“热重启”时它也会显示新的根页面。
Main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:lyric_hero/app_localizations.dart';
import 'package:lyric_hero/blocs/unlogged_bloc.dart';
import 'package:lyric_hero/blocs/userrepository_bloc.dart';
import 'package:lyric_hero/pages/LoggedPage.dart';
import 'package:lyric_hero/pages/SplashScreenPage.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:lyric_hero/pages/UnloggedPage.dart';
import 'package:provider/provider.dart';
void main() {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: Colors.black,
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark));
return runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<UnloggedBloc>.value(value: UnloggedBloc()),
ChangeNotifierProvider<UserRepository>.value(
value: UserRepository.instance())
],
child: MaterialApp(
title: 'Lyric Hero',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
supportedLocales: [
Locale('en', 'US'),
Locale('es', 'ES'),
Locale('pt', 'BR')
],
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
localeResolutionCallback: (locale, supportedLocales) {
for (var supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale?.languageCode) {
return supportedLocale;
}
}
return supportedLocales.first;
},
),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => UserRepository.instance(),
child: Consumer(
builder: (context, UserRepository user, _) {
switch (user.status) {
case Status.Uninitialized:
return SplashScreenPage();
case Status.Unauthenticated:
case Status.Authenticating:
return UnloggedPage();
case Status.Authenticated:
return LoggedPage();
}
},
),
);
}
}
User_repository_bloc
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:firebase_auth/firebase_auth.dart';
enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }
class UserRepository with ChangeNotifier {
FirebaseAuth _auth;
FirebaseUser _user;
Status _status = Status.Uninitialized;
UserRepository.instance() : _auth = FirebaseAuth.instance {
_auth.onAuthStateChanged.listen(_onAuthStateChanged);
}
Status get status => _status;
FirebaseUser get user => _user;
Future<bool> signIn(String email, String password) async {
try {
_status = Status.Authenticating;
notifyListeners();
await _auth.signInWithEmailAndPassword(email: email, password: password);
return true;
} catch (e) {
_status = Status.Unauthenticated;
notifyListeners();
return false;
}
}
Future signOut() async {
_auth.signOut();
_status = Status.Unauthenticated;
notifyListeners();
return Future.delayed(Duration.zero);
}
Future<void> _onAuthStateChanged(FirebaseUser firebaseUser) async {
print(firebaseUser.toString());
if (firebaseUser == null) {
new Timer(Duration(seconds: 4), () {
_status = Status.Unauthenticated;
notifyListeners();
});
} else {
_user = firebaseUser;
_status = Status.Authenticated;
notifyListeners();
}
}
}
未登录页面
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:lyric_hero/blocs/unlogged_bloc.dart';
import 'package:lyric_hero/widgets/AppTitle.dart';
import 'package:lyric_hero/widgets/Unlogged/BottomMessage.dart';
import 'package:lyric_hero/widgets/Unlogged/LoginForm.dart';
import 'package:lyric_hero/widgets/Unlogged/RegisterForm.dart';
import 'package:lyric_hero/widgets/gradients/BluePurpleGradient.dart';
import 'package:responsive_widgets/responsive_widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provider/provider.dart';
import 'package:page_transition/page_transition.dart';
class UnloggedPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _UnloggedPageState();
}
}
class _UnloggedPageState extends State<UnloggedPage> {
@override
void initState() {
new Timer(Duration(seconds: 1), () {
Navigator.push(
context,
PageTransition(
type: PageTransitionType.rightToLeft, child: UnloggedForms()));
});
super.initState();
}
@override
Widget build(BuildContext context) {
ResponsiveWidgets().init(context,
referenceHeight: 1920, // Optional
referenceWidth: 1080, // Optional
referenceShortestSide: 411 // Optional, default = 360
);
return Scaffold(
body: BlueGreenGradient(
child: Center(
child: AppTitle(
type: 'white',
),
),
),
);
}
}
class UnloggedForms extends StatelessWidget {
Widget horizontalLine() => Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Container(
width: ScreenUtil.getInstance().setWidth(120),
height: 1.0,
color: Colors.black26.withOpacity(.2),
),
);
@override
Widget build(BuildContext context) {
final UnloggedBloc unloggedBloc = Provider.of<UnloggedBloc>(context);
Timer(Duration(seconds: 2), () {
unloggedBloc.setPaddingBottom(50);
unloggedBloc.setPaddingTop(50);
unloggedBloc.setAlignment(Alignment.topCenter);
});
ResponsiveWidgets().init(context,
referenceHeight: 1920, // Optional
referenceWidth: 1080, // Optional
referenceShortestSide: 411 // Optional, default = 360
);
return Container(
color: Colors.white,
child: SafeArea(
child: Scaffold(
body: Container(
color: Colors.white,
child: AnimatedContainer(
duration: Duration(milliseconds: 400),
onEnd: () {
Timer(Duration(milliseconds: 400), () {
unloggedBloc.setShow();
});
},
alignment: unloggedBloc.alignment,
child: SingleChildScrollView(
padding: EdgeInsetsResponsive.only(
top: unloggedBloc.paddingtop,
bottom: unloggedBloc.paddingbottom),
child: Column(children: <Widget>[
AppTitle(
type: 'main-gradient',
),
Visibility(
visible: unloggedBloc.show,
child: Column(
children: <Widget>[
unloggedBloc.root,
BottomMessagge(
login: unloggedBloc.login,
action: () {
if (unloggedBloc.login) {
unloggedBloc
.setRoot(RegisterForm());
} else {
unloggedBloc.setRoot(LoginForm());
}
unloggedBloc.setLogin();
},
)
],
))
])))))));
}
}
登录表单
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:lyric_hero/app_localizations.dart';
import 'package:lyric_hero/blocs/userrepository_bloc.dart';
import 'package:lyric_hero/widgets/CustomizedButton.dart';
import 'package:provider/provider.dart';
import 'package:responsive_widgets/responsive_widgets.dart';
import 'package:gradient_widgets/gradient_widgets.dart';
import 'package:responsive_widgets/responsive_widgets.dart';
import 'package:flutter_signin_button/flutter_signin_button.dart';
class LoginForm extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _LoginFormState();
}
}
class _LoginFormState extends State<LoginForm> {
TextEditingController _email;
TextEditingController _password;
double _formheight = 550.0;
final _formKey = GlobalKey<FormState>();
Widget horizontalLine() => Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Container(
width: ScreenUtil.getInstance().setWidth(120),
height: 1.0,
color: Colors.black26.withOpacity(.2),
),
);
@override
void initState() {
_email = TextEditingController(text: "");
_password = TextEditingController(text: "");
super.initState();
}
@override
Widget build(BuildContext context) {
final user = Provider.of<UserRepository>(context, listen: false);
ResponsiveWidgets().init(context,
referenceHeight: 1920, // Optional
referenceWidth: 1080, // Optional
referenceShortestSide: 411 // Optional, default = 360
);
ScreenUtil.instance = ScreenUtil.getInstance()..init(context);
ScreenUtil.instance =
ScreenUtil(width: 750, height: 1334, allowFontScaling: true);
return Padding(
padding: EdgeInsetsResponsive.only(top: 30, right: 20, left: 20),
child: Column(children: <Widget>[
ContainerResponsive(
width: double.infinity,
height: _formheight,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, 15.0),
blurRadius: 15.0),
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, -10.0),
blurRadius: 10.0),
]),
child: Padding(
padding: EdgeInsets.only(left: 16.0, right: 16.0, top: 16.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(AppLocalizations.of(context).translate('signin-title'),
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(45),
fontFamily: "Poppins-Bold",
letterSpacing: .6)),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Text(AppLocalizations.of(context).translate('email'),
style: TextStyle(
fontFamily: "Poppins-Medium",
fontSize: ScreenUtil.getInstance().setSp(26))),
TextFormField(
controller: _email,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value.isEmpty) {
setState(() {
_formheight = 620;
});
return AppLocalizations.of(context)
.translate('email_empty');
}
return null;
},
decoration: InputDecoration(
hintText: AppLocalizations.of(context)
.translate('email')
.toLowerCase(),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: ScreenUtil.getInstance().setSp(23))),
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Text(AppLocalizations.of(context).translate('password'),
style: TextStyle(
fontFamily: "Poppins-Medium",
fontSize: ScreenUtil.getInstance().setSp(26))),
TextFormField(
controller: _password,
obscureText: true,
validator: (value) {
if (value.isEmpty) {
setState(() {
_formheight = 620;
});
return AppLocalizations.of(context)
.translate('password_empty');
}
return null;
},
decoration: InputDecoration(
hintText: AppLocalizations.of(context)
.translate('password')
.toLowerCase(),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: ScreenUtil.getInstance().setSp(23))),
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(35),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
AppLocalizations.of(context).translate('forgot-btn'),
style: TextStyle(
color: Colors.blue,
fontFamily: "Poppins-Medium",
fontSize: ScreenUtil.getInstance().setSp(28)),
)
],
),
user.status == Status.Authenticating
? Center(
child: Padding(
padding: EdgeInsetsResponsive.only(top: 40),
child: CircularProgressIndicator(),
))
: CustomizedButton(
width: 700,
height: 100,
color1: Color(0xFF17ead9),
color2: Color(0xFF6078ea),
text: AppLocalizations.of(context)
.translate('signin-btn'),
action: () async {
print("EMAIL: " + _email.text.toString());
print("PASSWORD: " + _password.text.toString());
if (_formKey.currentState.validate()) {
setState(() {
_formheight = 550;
});
if (!await user.signIn(
_email.text, _password.text)) {
print(Text("something is wrong"));
}
/*_key.currentState.showSnackBar(SnackBar(
content: Text("Something is wrong"),
));()
*/
}
})
],
),
),
),
),
Padding(
padding: EdgeInsetsResponsive.only(top: 20, bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
horizontalLine(),
Text(AppLocalizations.of(context).translate('social-title'),
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(35),
fontFamily: "Poppins-Medium")),
horizontalLine()
],
),
),
SignInButton(
Buttons.Facebook,
mini: false,
text: AppLocalizations.of(context).translate('fb-login-btn'),
onPressed: () {},
),
SignInButton(
Buttons.Google,
mini: false,
text: AppLocalizations.of(context).translate('go-login-btn'),
onPressed: () {},
),
]));
}
@override
void dispose() {
_email.dispose();
_password.dispose();
super.dispose();
}
}
为什么您对UserRepository有两个相同的ChangeNotifierProvider?从“主页”中,删除第一棵树ChangeNotifierProvider。将消费者放在顶部