2017-04-27 204 views
2

我有这个应用程序从远程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场和assing summarylast两个变量:

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都是复合对象。

在我的窗口小部件build功能,我将显示这两个对象的内容:

new TextSpan(
    text: numFormatter.format(int.parse(_bs['bc'])), 
    style: aboutTextStyle, 
), 

程序编译确定,但推出的时候,快速闪红屏将出现:

enter image description here

很快,正确的屏幕将出现:enter image description here

我知道在最初的build期间,对象_bs_lb尚未存在,并且对远程API的异步调用仍在尝试填充返回的响应,因此在这种情况下,将无法调用_bs['bc']。因此弹出非阻塞错误。

解决方法

我可以通过声明一组变量消除这个错误,并在initState功能为它们分配;而不是渲染_bs['bc'],我会渲染一个新变量_bookCoount。这样,渲染将在没有这个红色屏幕的情况下完成,并且该变量的值最初将为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, 
), 
+0

这可以解决。比我声明所有变量更好。 – TaylorR