Flutter 提供者和小部件生命周期
Posted
技术标签:
【中文标题】Flutter 提供者和小部件生命周期【英文标题】:Flutter provider and widget lifecycle 【发布时间】:2021-08-12 19:40:23 【问题描述】:我有一个简单的流程:
一个 UserModel
实现 ChangeProvider
,它包装了用户的状态(如果它已登录并且实用程序让他登录/注销)。特别是注销看起来像:
void logout()
user = null;
notifyListeners();
UserPage
小部件(其中包括):
class UserPage extends StatelessWidget
@override
Widget build(BuildContext context)
// ... adding only relevant code
// a text with the user first letter of the email
Text(context.watch<UserModel>().user.email[0])
// a logout button with the following onPressed method
TextButton( \\ ...
onPressed: ()
context.read<UserModel>().logout();
Navigator.pop(context);
)
我期待按下注销并弹出UserPage
小部件不会让颤振重建它。但事实并非如此,logout
方法中的notifyListeners()
使颤振重建小部件并触发NullPointerException
(因为用户为空且无法访问电子邮件)。
我可以处理它(检查用户对象是否为 != null 但我想了解为什么会发生这种情况)。
假设pop
破坏了小部件是否正确?如果不是,我应该如何处理这种情况?
当用户注销时,我不想在内存中拥有这个小部件,也不想处理它的存在。我希望在用户登录时创建一个UserPage
,并在注销后将其销毁
【问题讨论】:
【参考方案1】:当您调用 logout
时,watch
在这行 Text(context.watch<UserModel>().user.email[0])
将导致它所在的小部件重建。
你需要在你调用的push
的回调中调用logout
来推送这个页面。 pop
还可以发送值来告知成功或失败等条件。
所以应该是这样的:
Navigator.pushNamed(context, some_route).then(value)
context.read<UserModel>().logout();
回调中的value
可以从pop
返回,就像Navigator.of(context).pop(true);
一样
这将确保 logout
仅在小部件弹出后才被调用。
如果您不喜欢回调,可以使用 async
await
模式。
【讨论】:
谢谢,你的回答,然后谷歌搜索找到了这个(flutter.dev/docs/cookbook/navigation/returning-data),它有帮助!现在虽然屏幕弹出,然后注销过程(网络调用)开始,然后UserPage
被刷新。有没有办法确保在注销程序完成后显示UserPage
屏幕?
你明白了!假设您正在使用一个屏幕进行登录和用户页面,这些只是一个屏幕,某些状态决定了 UI 将显示什么。在这种情况下,您不需要弹出屏幕,因为通过调用 logout
完成重建就足够了 - 您只需要编写逻辑来处理基于用户状态显示的内容被登录在与否。如果你有单独的屏幕那么你可以使用popAndReplace
,但绝对不要弹出,并推送同一个屏幕。以上是关于Flutter 提供者和小部件生命周期的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:在从小部件树中删除时或在其生命周期结束时为小部件设置动画?
Flutter:在构造函数中调用 setState():_SharesListState#6c96a(生命周期状态:已创建,无小部件,未安装)