我如何得到JSON数据,然后把它放在另一个变量,而不必担心未来的方法



在我的用例中,我必须用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();
              }
            }),
      ),
    );
  }
}

最新更新