Flutter实战指南
上QQ阅读APP看书,第一时间看更新

2.19 Flutter中解除状态的特性

现在深入研究一些高级特性,首先新建文件news_control.dart,在NewsManager中找到添加按纽,把这个按钮拆分成小部件,放到news_control.dart文件中。在news_control.dart中引入flutter/material包,创建NewsControl小部件,此时它是有状态的还是无状态的?它应该是一个无状态的,因为这里只显示一个按钮,不需要接收任何外部数据,只是渲染一个静态按钮,所以这是一个不需要改变的小部件。

接下来添加build()方法,返回按钮对应的小部件,代码如下:

显然这里不能使用setState()方法。我们希望在NewsManager中管理news数据,所以NewsManager是有状态的小部件。NewsManager是NewsControl小部件和News小部件的纽带。解除状态的概念是什么?解除状态是在一个小部件中管理状态,这个小部件可以访问所有其他的小部件,NewsManager是连接小部件,它可以触及状态的变化。

现在的问题是怎样把NewsControl中的按钮单击事件传递给NewsManager,然后让NewsManager调用setState()方法。首先在_NewsManagerState类中创建一个方法,代码如下:

_addNews()方法返回值为空,以下画线开始,表明这个方法只会在这个文件中使用,_addNews()方法需要一个新的news作为参数,类型是String。

现在的问题是怎样通过单击按钮来调用这个_addNews()方法?按钮在另外一个小部件中,这里就涉及解除状态的概念,解除状态是把所有跟状态有关系的小部件的状态提取出来,放到一个有状态的小部件中,然后再通过这个有状态的小部件控制所有被提取状态的小部件。

被提取状态的小部件NewsControl需要访问NewsManager中的_addNews()方法,在NewsManager中,可以将引用传递给具有访问权限的小部件,所以可以把_addNews()作为一个参数传递给NewsControl。请注意这里不是执行,所以不能加小括号,代码如下:

如果_addNews后加小括号,表示当调用build()方法时,会直接调用_addNews()方法,那么这个_addNews()方法只会传递给NewsControl一个void值。这里不应该传递一个返回值,而应该是_addNews()这个方法的引用,即传递了这个方法的地址给NewsControl。在NewsControl中,把方法参数写到构造器里,代码如下:

NewsControl构造器接收方法引用,然后保存到NewsControl的方法属性中,Function在Dart语言中是一个单独的类型,它表示这个属性可以存储方法的引用,在参数中输入this.addNews,确保构造中接收到的内容参数会被绑定到这个方法属性中。

这样NewsControl就可以访问NewsManager小部件中的方法了,即使在NewsControl小部件中没有定义_addNews()方法。