Flutter中Provider的dispose方法未触发问题咨询
问题原因
你当前的代码只是通过Provider.of获取了ForgotPasswordPageProvider的实例,但这个Provider的生命周期并没有和ForgotPasswordPage绑定在一起。只有当Provider是在页面的作用域内创建(比如用ChangeNotifierProvider包裹页面),页面销毁时才会触发Provider的dispose方法。
解决方案
有两种常用的方式可以让Provider和页面生命周期绑定,触发dispose:
方式一:在GoRouter路由配置中绑定Provider
修改你的GoRouter路由配置,用ChangeNotifierProvider包裹ForgotPasswordPage,这样页面出栈时Provider会自动调用dispose:
GoRoute( path: '/forgot-password', builder: (context, state) { return ChangeNotifierProvider( create: (_) => ForgotPasswordPageProvider(), child: const ForgotPasswordPage(), ); }, )
方式二:在页面内部包裹Provider
修改ForgotPasswordPage的build方法,用ChangeNotifierProvider作为根组件,确保Provider和页面同生命周期:
@override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (_) => ForgotPasswordPageProvider(), child: Consumer<ForgotPasswordPageProvider>( builder: (context, provider, child) { return Scaffold( appBar: CustomAppBar( leading: IconButton( onPressed: () { GoRouter.of(context).pop(); }, icon: const FaIcon(FontAwesomeIcons.xmark), ), title: "Reset password", ), body: Padding( padding: EdgeInsets.symmetric( horizontal: 24, vertical: MediaQuery.of(context).size.height * 0.06), child: Form( key: provider.formKey, child: Column( children: [ Hero( tag: "logo", child: FaIcon( FontAwesomeIcons.comments, color: Theme.of(context).colorScheme.primary, size: 96, ), ), SizedBox(height: MediaQuery.of(context).size.height * 0.02), FormInputField( controller: provider.textEditingController, hintText: "Enter your email address", keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.done, validator: FormValidator.emailValidator, label: "E-mail", ), SizedBox(height: MediaQuery.of(context).size.height * 0.02), FilledButton( onPressed: () { if (provider.formKey.currentState!.validate()) {} }, child: const Text("Reset password"), ), ], ), ), ), ); }, ), ); }
补充说明
- 不要直接在全局或者上层作用域创建这个Provider,否则页面销毁时Provider不会被销毁,也就不会触发dispose。
- 用
Consumer而非直接Provider.of可以避免不必要的组件重建,优化页面性能。
内容的提问来源于stack exchange,提问作者Abel
相关产品推荐
相关产品推荐

