1

我有一个简单的流程:

  • 包装用户状态的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小部件不会让颤动重建它。然而事实并非如此,notifyListeners()inlogout方法使颤振重建小部件并触发 a NullPointerException(因为用户为 null 并且无法访问电子邮件)。

我可以处理它(检查用户对象是否为 != null 但我想了解为什么会发生这种情况)。

pop假设破坏小部件是否正确?如果不是,我应该如何处理这种情况?当用户注销时,我不想在内存中拥有这个小部件,也不想处理它的存在。我希望UserPage在用户登录时创建一个并在注销后销毁它

4

1 回答 1

1

When you call logout , watch in this line Text(context.watch<UserModel>().user.email[0]) will cause the widget it's in to rebuild.

You need to call logout in the call back of push the one you called to push this page. pop can also send values to inform about the conditions like success or failure.

So it would be something like this:

Navigator.pushNamed(context, some_route).then(value) {
context.read<UserModel>().logout();  
}

value in the call back can be returned from pop like so Navigator.of(context).pop(true);

This will ensure that logout is only called after the widget has been popped.

If you don't like callbacks you can use async await pattern.

于 2021-05-24T14:02:00.967 回答