I'm getting this error
E/flutter ( 9610): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: A CustRegViewModel was used after being disposed.
E/flutter ( 9610): Once you have called dispose() on a CustRegViewModel, it can no longer be used.
I have a View named CustRegView where I take a phone number form the user and send it to ViewModel named CustRegViewModel to authenticate which is supposed to return true or false base on its authentication. I am not disposing CustRegViewModel anywhere.
class CustRegView extends StatefulWidget {
@override
_CustRegViewState createState() => _CustRegViewState();
}
class CustRegView extends StatelessWidget{
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return BaseView<CustRegViewModel>(
builder: (context, model, child) => Scaffold(
...<some code>
FlatButton (
onPressed: () async {
var registerSuccess = await model.register( _controller.text, context);
// ^^^^^^^^^^^ HERE I AM GETTING AN ERROR IN ABOVE LINE ^^^^^^^^^^^
if (registerSuccess) {
Navigator.pushNamed(context, 'newScreen');
} else {
UIHelper().showErrorButtomSheet(context, model.errorMessage);
}
)
}
CustRegViewModel looks like this
class CustRegViewModel extends BaseViewModel {
final AuthService _authService = locator<AuthService>();
final DialogService _dialogService = locator<DialogService>();
dynamic newUserResult;
dynamic verifyResult;
Future<bool> register(String phoneNo, BuildContext context) async {
await verifyPhone;
return verifyResult ? true : false; // From here it returns true
}
Future<void> verifyPhone(phoneNo) async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: updatedPhoneNo,
timeout: Duration(seconds: 50),
verificationCompleted: (AuthCredential authCred) async {...... <some code>
verificationFailed: (AuthException authException) {...... <some code>
codeSent: (String verID, [int forceCodeResend]) async {...... <some code>
codeAutoRetrievalTimeout: (String verID) {...
).catchError((error) {...... <some code>
}
}
BaseViewlooks like this
class BaseView<T extends BaseViewModel> extends StatefulWidget {
final Widget Function(BuildContext context, T model, Widget child) builder;
final Function(T) onModelReady;
BaseView({this.builder, this.onModelReady});
@override
_BaseViewState<T> createState() => _BaseViewState<T>();
}
class _BaseViewState<T extends BaseViewModel> extends State<BaseView<T>> {
T model = locator<T>();
@override
void initState() {
if (widget.onModelReady != null) {
widget.onModelReady(model);
}
super.initState();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<T>(
create: (context) => model,
child: Consumer<T>(builder: widget.builder),
);
}
}
BaseViewModellooks like this
class BaseViewModel extends ChangeNotifier {
ViewState _state = ViewState.Idle;
ViewState get state => _state;
void setState(ViewState viewState) {
_state = viewState;
notifyListeners();
}
}
As the documentation of ChangeNotifier provider says, do not use the default constructor if you are reusing an existing ChangeNotifier
See https://pub.dev/documentation/provider/latest/provider/ChangeNotifierProvider-class.html
As the documentation of ChangeNotifier provider says, do not use the default constructor if you are reusing an existing
ChangeNotifierSee https://pub.dev/documentation/provider/latest/provider/ChangeNotifierProvider-class.html
Thanks for the response. Where I'm using the default constructor? I read that document and still don't know what I am doing wrong in my code.
ChangeNotifierProvider
ChangeNotifierProvider should be ChangeNotifierProvider.value
After changing this to .value, I'm getting below error
E/flutter (16830): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Looking up a deactivated widget's ancestor is unsafe.
E/flutter (16830): At this point the state of the widget's element tree is no longer stable.
E/flutter (16830): To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
On mentioned part here, in the above code
FlatButton (
onPressed: () async {
var registerSuccess = await model.register( _controller.text, context);
if (registerSuccess) {
Navigator.pushNamed(context, 'newScreen'); // <------ E R R O R H E R E
} else {
UIHelper().showErrorButtomSheet(context, model.errorMessage);
}
)
Why is that?
It sounds like a completely different issue.
My guess is that you are calling context.read inside dispose
It sounds like a completely different issue.
My guess is that you are calling
context.readinsidedispose
Yes, It was indeed different. That was my childish mistake. I was trying to push from a context which is popped before the push() method call. Thanks for your response