Closed premtemp1 closed 5 years ago
No you don't.
Simply inject FirebaseAuthService()
into your provider in main.dart
:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Provider<AuthService>(
builder: (_) => FirebaseAuthService(),
dispose: (_, AuthService authService) => authService.dispose(),
child: MaterialApp(
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: LandingPage(),
),
);
}
}
As a result, you could also remove the dispose()
method from both AuthService
and FirebaseAuthService
(this was only needed as the adapter uses StreamController
s that need to be disposed).
Thanks.. Please consider doing a deep dive on how to create a lazy loading list that get another set of record when the user scroll to the end. The list should scroll backward and forward and save the previous position... The API should take a page could and number of record to display
Thanks
@bizz84 well I receive this error every time I try to signup while trying to implement your solution working only with FirebaseAuthService()
, and also getting rid of the dispose()
method:
E/flutter (32103): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: A SignInModel was used after being disposed. E/flutter (32103): Once you have called dispose() on a SignInModel, it can no longer be used. E/flutter (32103): #0 _SignInModel&Object&EmailAndPasswordValidators&ChangeNotifier._debugAssertNotDisposed.
(package:flutter/src/foundation/change_notifier.dart:105:9) E/flutter (32103): #1 _SignInModel&Object&EmailAndPasswordValidators&ChangeNotifier._debugAssertNotDisposed (package:flutter/src/foundation/change_notifier.dart:111:6) E/flutter (32103): #2 _SignInModel&Object&EmailAndPasswordValidators&ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:200:12) E/flutter (32103): #3 SignInModel.updateWith (package:firebase_auth_demo_flutter/app/sign_in/sign_in_model.dart:77:5) E/flutter (32103): #4 SignInModel.submit (package:firebase_auth_demo_flutter/app/sign_in/sign_in_model.dart:47:7) E/flutter (32103):
@MRANASSPRO That's curious, that doesn't happen to me. Can you post the code for the sign in page that generates the error?
Pretty much the same code in the master branch, just got rid of the mock service, using only the FirebaseAuthService()
as the provider´s builder, the error is being generated when clicking on the submit button on either sign up or sign in.
Here is updated sign_in_page:
import 'package:firebase_auth_demo_flutter/app/sign_in/sign_in_model.dart';
import 'package:firebase_auth_demo_flutter/common_widgets/form_submit_button.dart';
import 'package:firebase_auth_demo_flutter/common_widgets/platform_alert_dialog.dart';
import 'package:firebase_auth_demo_flutter/common_widgets/platform_exception_alert_dialog.dart';
import 'package:firebase_auth_demo_flutter/constants/strings.dart';
import 'package:firebase_auth_demo_flutter/services/auth_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
class SignInPageBuilder extends StatelessWidget {
@override
Widget build(BuildContext context) {
final AuthService auth = Provider.of<AuthService>(context);
return ChangeNotifierProvider<SignInModel>(
builder: (_) => SignInModel(auth: auth),
child: Consumer<SignInModel>(
builder: (_, SignInModel model, __) => SignInPage._(model: model),
),
);
}
}
class SignInPage extends StatefulWidget {
const SignInPage._({Key key, @required this.model}) : super(key: key);
final SignInModel model;
@override
_SignInPageState createState() => _SignInPageState();
}
class _SignInPageState extends State<SignInPage> {
final FocusNode _emailFocusNode = FocusNode();
final FocusNode _passwordFocusNode = FocusNode();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
SignInModel get model => widget.model;
@override
void dispose() {
_emailFocusNode.dispose();
_passwordFocusNode.dispose();
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
void _showSignInError(SignInModel model, PlatformException exception) {
PlatformExceptionAlertDialog(
title: model.errorAlertTitle,
exception: exception,
).show(context);
}
void _unfocus() {
_emailFocusNode.unfocus();
_passwordFocusNode.unfocus();
}
Future<void> _submit() async {
_unfocus();
try {
final bool success = await model.submit();
if (success) {
if (model.formType == SignInFormType.forgotPassword) {
PlatformAlertDialog(
title: Strings.resetLinkSentTitle,
content: Strings.resetLinkSentMessage,
defaultActionText: Strings.ok,
).show(context);
} else {
//print('context check: $context ');
Navigator.of(context).pop();
}
}
} on PlatformException catch (e) {
_showSignInError(model, e);
}
}
void _emailEditingComplete() {
final FocusNode newFocus = model.canSubmitEmail ? _passwordFocusNode : _emailFocusNode;
FocusScope.of(context).requestFocus(newFocus);
}
void _updateFormType(SignInFormType formType) {
model.updateFormType(formType);
_emailController.clear();
_passwordController.clear();
}
Widget _buildEmailField() {
return TextField(
controller: _emailController,
focusNode: _emailFocusNode,
decoration: InputDecoration(
labelText: Strings.emailLabel,
hintText: Strings.emailHint,
errorText: model.emailErrorText,
enabled: !model.isLoading,
),
autocorrect: false,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.emailAddress,
keyboardAppearance: Brightness.light,
onChanged: model.updateEmail,
onEditingComplete: _emailEditingComplete,
inputFormatters: <TextInputFormatter>[
model.emailInputFormatter,
],
);
}
Widget _buildPasswordField() {
return TextField(
controller: _passwordController,
focusNode: _passwordFocusNode,
decoration: InputDecoration(
labelText: model.passwordLabelText,
errorText: model.passwordErrorText,
enabled: !model.isLoading,
),
obscureText: true,
autocorrect: false,
textInputAction: TextInputAction.done,
keyboardAppearance: Brightness.light,
onChanged: model.updatePassword,
onEditingComplete: _submit,
);
}
Widget _buildContent() {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(height: 8.0),
_buildEmailField(),
if (model.formType != SignInFormType.forgotPassword) ...<Widget>[
SizedBox(height: 8.0),
_buildPasswordField(),
],
SizedBox(height: 8.0),
FormSubmitButton(
text: model.primaryButtonText,
loading: model.isLoading,
onPressed: model.isLoading ? null : _submit,
),
SizedBox(height: 8.0),
FlatButton(
child: Text(model.secondaryButtonText),
onPressed: model.isLoading ? null : () => _updateFormType(model.secondaryActionFormType),
),
if (model.formType == SignInFormType.signIn)
FlatButton(
child: Text(Strings.forgotPasswordQuestion),
onPressed: model.isLoading ? null : () => _updateFormType(SignInFormType.forgotPassword),
),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 2.0,
title: Text(model.title),
),
backgroundColor: Colors.grey[200],
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Card(
child: Padding(
padding: EdgeInsets.all(16.0),
child: _buildContent(),
),
),
),
),
);
}
}
@MRANASSPRO sorry for the late reply. Do you present the sign-in page with a call to Navigator.push, or is it built at the root of the navigation stack?
@bizz84 Hey Andrea, I am really sorry that was my mistake, I removed the SignInPageBuilder class, that contains a Provider of AuthService, now I fixed it and it worked perfectly :) I will remove the issue, my sincere apologies I am looking forward to contact you via email if possible
Hello, Thanks for the article.. I like the mock service but I don't want to use it now.. Do I still need the adapter class?
Thanks