用 Provider 提供的数据发生变化以后,如果想重建使用这些数据的小部件,我们要使用 Provider 提供的 ChangeNotifierProvider 提供 ChangeNotifier 类型的数据。
先这样试一下,打开 auth_login_form,在这个小部件里复制一份这个 loginButton,然后修改一下名字,换成 logoutButton,修改一下按钮文字,设置成退出登录,在按钮的 onPressed 里面执行一下 authModel 里面提供的 logout 这个方法。
再修改一下 Container 的 child 属性的值,这里可以判断一下 authModel 的 isLoggedIn ,如果它是 true,这里可以用一下 logoutButton 如果是 false 就用一下 loginButton,也就是显示登录按钮。
打开编辑器的调试,重启一下。然后打开练习页面,按一下登录按钮,这样会执行 authModel 里的 login 方法,它会把 isLoggedIn 的值修改成 true,不过你会发现这里在界面上并没有显示出退出登录按钮。
ChangeNotifier
打开 auth_model,这里我们让这个 AuthModel 类继承一下 ChangeNotifier,这样在这个类里面,当属性的值发生变化的时候可以执行一下 notifyListeners() ,这样所有监听了这个类的小部件就会被重建。在这个 login 方法里面执行一下 notifyListeners() 。然后在这个 logout 方法里面也执行一下 notifyListeners() 。
打开 app.dart,现在这里用的是 Provider 提供的 AuthModel 实例,现在这个 AuthModel 类是一个 ChangeNotifier ,所以要提供这个类的实例的时候,就不能再用 Provider 了,这里要把它换成 ChangeNotifierProvider。
打开练习页面,按一下登录按钮,执行了 authModel 里的 login 方法,修改了 isLoggedIn 属性的值,执行了 notifyListeners() ,小部件被重建了,因为 authModel.isLoggedIn 的值是 true ,所以这里显示的就会是退出登录按钮。
按一下退出登录按钮,authModel.isLoggedIn 会被修改成 false,小部件又会被重建,现在又会显示登录按钮。使用在这里提供的这个 AuthModel 实例的小部件默认都会监听它,所以在执行 notifyListeners() 的时候这些小部件就会被重建。
listen
有个参数可以控制是否要重建小部件,因为很可能有些小部件不需要重建,重建会浪费一些资源。打开 auth_login_form,这个 Provider.of 方法的第二个参数是 listen,把它设置成 false,这就相当于是取消监听,也就是在执行 notifyListeners() 的时候,这个小部件也就不会被重建。默认这个 listen 参数的值是 true,这个小部件需要重建,所以我们可以把这个 listen 设置成 true。