在我的用例中,我必须用JSON数据改变应用程序的布局。我有一个JSON文件,我想获取并使用键值,而不使用下一个方法中的Future方法,而我想放置映射的JSON并将其放在空花括号中:
这是我抓取的JSON文件:
# test_json.json
{
"fontSize" : "10",
"fontFamily" : "A",
"fontWeigth" : "bold",
"fontColor" : "blue"
}
这是抓取JSON文件并对其进行映射的文件:
# get_json.dart
class GetJson{
Future<Map<String, dynamic>> getJson() async {
String jsonData =
await rootBundle.loadString('assets/json/test_json.json');
Map<String, dynamic> data = jsonDecode(jsonData);
return data;
}
}
然后我抓住这个映射的JSON,我想把它放在一个名为mappedData
的变量中,并把它放在空花括号内。然后我想用getNumber()
获得数字,在这个方法中,我用另一个名为TypeConvertor.getDouble()
的自定义方法将fontSize
的类型从字符串转换为double:
class Utility {
var mappedData= {};
setJson() async {
mappedData = await GetJson().getJson();
}
getNumber(String key) {
var data = mappedData;
return TypeConvertor.getDouble(data[key]);
}
}
在我的用例中,我需要这样做,我没有其他选择。我想明确地抓住JSON,我不希望getNumber()
成为一个未来。然后我不能将Utility().getNumber("fontSize")
放置在有状态的小部件内,因为我必须使用setState
,我想避免这种情况,因为我会在fontSize
旁边有很多键,所以我必须为每个键值使用setState
。我只是想在fontSize
属性中使用Utility().getNumber("fontSize")
,其余的也像这样。在我的例子中,我必须这样做:
class TestView extends StatefulWidget {
const TestView({Key? key}) : super(key: key);
@override
State<TestView> createState() => _TestViewState();
}
class _TestViewState extends State<TestView> {
@override
Widget build(BuildContext context) {
return Text(
"test",
style: TextStyle(fontSize: Utility().getNumber("fontSize")),
);
}
}
但在我的应用程序mappedData
给出null。完整的错误是:Unhandled Exception: type 'Null' is not a subtype of type 'String'
,空值在mappedData
内。我想抓住json数据,并将其放在一个空的映射和使用映射json从那里开始。我如何解决null异常问题?
编辑
将变量更改为正确的版本
可能是因为在调用getNumber
之前没有调用setJson
。下面的代码可以工作。
final utility = Utility();
await utility.setJson();
print(utility.getNumber("fontSize"));
如果你想避免类似的错误,你有一些选择作为解决方案。
- 包含
mappedData
到实用程序的构造函数 - 将
getNumber
改为static,并添加参数mappedData
。 - 使用JsonSerializable(这有点困难,但最好的解决方案)
我找到了部分由@bakatsuyuki贡献的解决方案。所以我确实使用了await utility.setJson();
,但我也用initState()
初始化了它,所以字段utility
没有null
值。我还使用FutureBuilder()
来检查snapshot.hasData
,然后我用utilitiy
的数据显示Text()
小部件,否则显示空Container
。这样我可以解决null
异常。
这是为我工作的视图:
class AppView extends StatefulWidget {
const AppView({
Key? key,
}) : super(key: key);
@override
_AppViewState createState() => _AppViewState();
}
class _AppViewState extends State<AppView> {
final utility = Utility();
Future setUtility() async {
await utility.setJson();
}
@override
void initState() {
setUtility();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder(
future: AppContent().getAppContent(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("test",
style: TextStyle(
fontSize: utility.getNumber("fontSize"),
));
} else {
return Container();
}
}),
),
);
}
}