使用带有本地 JSON 作为未来的 FutureBuilder 时出错
Posted
技术标签:
【中文标题】使用带有本地 JSON 作为未来的 FutureBuilder 时出错【英文标题】:Error Using FutureBuilder With Local JSON as Future 【发布时间】:2021-04-05 01:22:35 【问题描述】:我正在尝试加载一些 json 数据并使用futurebuilder
来等待数据首先可用然后显示它。当我尝试在DetailsView
中加载数据时,我收到两条日志消息,说没有数据和空值,屏幕出错,然后恢复正常,json 记录到控制台。
抛出的异常是The following NoSuchMethodError was thrown building FutureBuilder<String>(dirty, state: _FutureBuilderState<String>#cc31b): The method '[]' was called on null. Receiver: null
。
示例代码:
body: Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 15.0),
child: FutureBuilder(
future: DefaultAssetBundle.of(context).loadString("assets/my_data.json"), // validly referenced in pubspec and in right folder
builder: (context, snapshot)
if(!snapshot.hasData)
print('no data'); // I understand it will be empty for now
else
print('hd');
var data = snapshot.data.toString();
print(data); // null logged to console, is the future still empty at this point?
final parsedData = json.decode(data);
print('pd $parsedData[1]'); // this line is where it shows the method [] was called on null
return data == null || data.isEmpty
? LoadingStrengths()
: MyDataText();
// : DailyStrengthText(day: widget.day, data: parsedData);
,
),
),
问题似乎是:
-
我没有正确处理未来
我没有正确解析 json,在下面附上了它的副本。
样本数据:
[
"1": "Each day is an opportunity to start over again"
,
"2": "Every man must at one point be tempted to hoist the black"
,
"3": "Be kind to everyone you meet"
]
我试图通过使用字符串化数字作为键来解析它,以访问值。如何为此创建模型类或/并在futurebuilder中解析此json?谢谢。
------------------- 编辑 --------------- ------------------------- 这是编辑后的构建器方法,我可以从中解析并打印出数据:
if(!snapshot.hasData)
print('no data yet');
return LoadingStrengths();
else
print('hd');
var data = snapshot.data.toString();
parsedData = json.decode(data);
print('pd $parsedData[widget.day - 1]');
return Text('$data[widget.day - 1]'); // it errors out here
当我将值分配给 Text 小部件时,它会出现以下错误消息:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building FutureBuilder<String>(dirty, state: _FutureBuilderState<String>#cc19b):
The method '[]' was called on null.
Receiver: null
Tried calling: [](4)
The relevant error-causing widget was:
FutureBuilder<String> file:///E:/FlutterProjects/daily_strength/lib/screens/DetailsView.dart:30:18
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 _DetailsViewState.build.<anonymous closure>
(package:daily_strength/screens/DetailsView.dart:47:34)
#2 _FutureBuilderState.build
(package:flutter/src/widgets/async.dart:751:55)
#3 StatefulElement.build
(package:flutter/src/widgets/framework.dart:4744:28)
#4 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:4627:15)
请问这是什么意思?我正在获取数据,但由于某种原因将其设置为文本小部件不起作用?谢谢。
【问题讨论】:
打印“无数据”后添加return
即使没有数据,我也会返回两个小部件。问题是当我试图打印出像 parseddata[1] 这样的解析后的 json 时。对吗?
这能回答你的问题吗? What is a NoSuchMethod error and how do I fix it?
【参考方案1】:
您正在尝试在 JSON 未加载时对其进行解码。添加了一些 cmets 进行说明。
if(!snapshot.hasData)
// Problem is here, Data has not arrived yet. You are just printing there is
// no data, but still moving on the next step
print('no data');
else
print('hd');
// data is null right now, toString() just return 'null' in string form
var data = snapshot.data.toString();
// null logged to console, is the future still empty at this point? yes exactly
print(data);
// 'null' is parsed has null is returned
final parsedData = json.decode(data);
// parsedData is null, you can't access using [], when it's null, that why exception is thrown
print('pd $parsedData[1]');
return data == null || data.isEmpty
? LoadingStrengths()
: MyDataText();
解决方案:
if(!snapshot.hasData)
return LoadingStrengths(); // return a loader when there is not data
else
// Do stuff when it is loaded;
【讨论】:
嗨,由于您的方法,您的回答似乎最有意义。我已经修改了代码以在将来没有数据时返回加载小部件,它没有显示(如何解决这个问题?)但至少它也不会出错。我想返回一个 Text(data) 小部件。我在哪里做这个?谢谢 嘿,谢谢。可以给个代码sn-p吗?【参考方案2】:创建一个单独的 Future 方法(在此处添加所有数据处理)并从 Futurebuilder 中调用它。这可能是导致问题的原因。还要使用 Postman 检查 API 是否正常工作
【讨论】:
显示代码 sn-p?另请查看我在其他答案下方的评论。谢谢【参考方案3】:您在 if 条件之外调用 data
。像这样将其包裹在 else 条件中
if (!snapshot.hasData)
print('no data'); // I understand it will be empty for now
else
print('hd');
var data = snapshot.data.toString();
print(data); // null wont be logged to console anymore
final parsedData = json.decode(data);
print('pd $parsedData[1]');
【讨论】:
谢谢先生。如何返回包含数据的小部件? 在if
语句中,data
尚不可用,因此请在此处返回您的LoadingStrengths
。在else
语句中返回您的Widget
将编辑问题以分享最近的错误。谢谢【参考方案4】:
这是有问题的:
future: DefaultAssetBundle.of(context).loadString("assets/my_data.json"),
这需要在一个变量中。想象一下这个 build() 被调用了 30 次。 .loadString 将被调用 30 次,你的 Future 永远不会完成!
始终将您的 Future 放入一个简单的 var,并在您的 FutureBuilder 中引用该简单的 var。不要在那里执行操作。
【讨论】:
以上是关于使用带有本地 JSON 作为未来的 FutureBuilder 时出错的主要内容,如果未能解决你的问题,请参考以下文章
如何使用本地 JSON 对象作为 jQuery DataTables 的数据源
使用 swift 在 Alamofire 中发送带有对象数组的 JSON 作为参数