我有这个应用程序从远程API获取一些数据。因此,我将接收并显示在JSON Future
中的数据:
{"status":200,"out":{"summary":[{"bc":"1876","wc":"488679","pc":"731904"}],"last":[{"id":"1877","place":"7","publisher":"-1","bookid":"01877","title":"Neither Civil Nor Servant","author":"Peh","region":"\u65b0\u52a0\u5761","copyrighter":"","translated":"0","purchdate":"2017-04-18","price":"200.00","pubdate":"2016-01-01","printdate":"2016-01-01","ver":"1.1","deco":"\u666e\u901a","kword":"0","page":"220","isbn":"978-981-4642-63-7","category":"","location":"","intro":"TT\u8d60\u4e66\u3002","instock":"1","p_name":"\uff08\u672a\u6307\u5b9a\uff09"}]}}
我将从此JSON中提取out
字段,并将summary
和last
分配给两个变量:
initState() async {
var getter = createHttpClient();
String uri='http://api.rsywx.com/book/summary';
var res=await getter.get(uri);
Map data=JSON.decode(res.body);
var out=data['out'];
setState(() {
_today=formatDate(new DateTime.now());
_lb=out['last'][0];
_bs=out['summary'][0];
_lb['purchdate']=formatDate(DateTime.parse(_lb['purchdate']));
});
}
所以_bs
和_lb
都是复合对象。
在我的widget build
函数中,我将显示这两个对象的内容:
new TextSpan(
text: numFormatter.format(int.parse(_bs['bc'])),
style: aboutTextStyle,
),
程序编译正常,但启动时会出现快速启动RED屏幕:
我知道在初始build
期间,对象_bs
,_lb
尚未存在,并且对远程API的异步调用仍在尝试填充返回的响应,因此在这种情况下,_bs['bc']
肯定不可调用。因此,弹出非阻塞错误。
解决方法
我可以通过声明一堆变量并在initState
函数中分配它们来消除此错误;而不是渲染_bs['bc']
,我将渲染一个新的变量_bookCoount
。这样,渲染将在没有此RED屏幕的情况下完成,并且该变量的值最初将为null
,并且很快将成为从远程API获取的正确值。
但是这太麻烦了,如果你理解我的意思:很多只使用一次的变量。
或者,我应该在父级别上获取数据,以便它作为道具传递给这个小部件吗?尚未尝试过。
非常感谢您的最佳实践输入。
更新
问题实际上来自int.parse
。如果我拿出那个电话,程序会安静地运行。
所以问题现在变成了
我会压缩int.parse
在它要解析的值变为有效之前提示错误。
答案 0 :(得分:1)
不确定您对解决方法的意思。在您的示例中setState()
在await getter.get(uri);
返回值之前不会被调用。
我想这应该做
new TextSpan(
text: _bs != null && _bs['bc'] != null ? [numFormatter.format(int.parse(_bs['bc'])) : 0,
style: aboutTextStyle,
),