Flutter 从本地存储的 JSON 文件中读取
Flutter read from locally stored JSON file
我有一个包含常见问题解答的本地 JSON 文件,我想将其数据作为列表加载,但我无法做到这一点。我使用的代码不呈现任何内容。请帮忙
这是有状态的小部件,我在其中调用我的 json 文件并想要呈现它。我想要的是一旦触发有状态小部件,也会触发 readJson 函数以将数据存储在名为 _items 的变量中。
class FAQScreen extends StatefulWidget {
FAQScreen({Key? key}) : super(key: key);
@override
State<FAQScreen> createState() => _FAQScreenState();
}
class _FAQScreenState extends State<FAQScreen> {
var _items = [];
void initState() {
readJson().then((value) => print("async done"));
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {},
icon: const Icon(Icons.arrow_back_outlined),
),
title: const Text('FAQ'),
centerTitle: true,
backgroundColor: const Color.fromARGB(255, 17, 82, 156),
),
body: ListView(
scrollDirection: Axis.vertical,
children: _items.map((itr) => faqTile(itr['title'])).toList(),
),
),
);
}
Future<void> readJson() async {
final String response =
await rootBundle.loadString('assets/FAQScreens/FAQlist.json');
final data = await json.decode(response);
setState(() {
_items = data;
});
}
}
下面是faqTile的定义:
Widget faqTile(String str) {
return InkWell(
onTap: () {},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Container(
child: ListTile(
onTap: () {},
contentPadding:
const EdgeInsets.only(left: 0.0, right: 0.0, top: 5, bottom:5),
title: Text(
str,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
trailing: const Icon(
Icons.arrow_forward_ios,
size: 18,
color: Color(0xff303030),
),
),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
width: 2.0,
color: Color(0xffcfd8dc),
),
),
),
),
),
);
}
虽然我认为您的代码应该可以工作,但如果在对 super
的调用完成之前完成,在 initState
中使用异步函数可能会导致麻烦。
首先,您是否将 JSON 文件作为资产添加到您的 pubspec.yaml
?
https://docs.flutter.dev/development/ui/assets-and-images
其次,为了防止出现异步问题,我会在您的 Widget 中使用 FutureBuilder
(您甚至可以使其成为无状态的)。
Widget build(BuildContext context) {
return FutureBuilder<Map<String, dynamic>>(
future: readJson(),
builder: (BuildContext context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
Map<String, dynamic> data = snapshot.data ?? {};
return MyAwesomeViewWithJsonData(data: data);
}
);
}
我有一个包含常见问题解答的本地 JSON 文件,我想将其数据作为列表加载,但我无法做到这一点。我使用的代码不呈现任何内容。请帮忙 这是有状态的小部件,我在其中调用我的 json 文件并想要呈现它。我想要的是一旦触发有状态小部件,也会触发 readJson 函数以将数据存储在名为 _items 的变量中。
class FAQScreen extends StatefulWidget {
FAQScreen({Key? key}) : super(key: key);
@override
State<FAQScreen> createState() => _FAQScreenState();
}
class _FAQScreenState extends State<FAQScreen> {
var _items = [];
void initState() {
readJson().then((value) => print("async done"));
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {},
icon: const Icon(Icons.arrow_back_outlined),
),
title: const Text('FAQ'),
centerTitle: true,
backgroundColor: const Color.fromARGB(255, 17, 82, 156),
),
body: ListView(
scrollDirection: Axis.vertical,
children: _items.map((itr) => faqTile(itr['title'])).toList(),
),
),
);
}
Future<void> readJson() async {
final String response =
await rootBundle.loadString('assets/FAQScreens/FAQlist.json');
final data = await json.decode(response);
setState(() {
_items = data;
});
}
}
下面是faqTile的定义:
Widget faqTile(String str) {
return InkWell(
onTap: () {},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Container(
child: ListTile(
onTap: () {},
contentPadding:
const EdgeInsets.only(left: 0.0, right: 0.0, top: 5, bottom:5),
title: Text(
str,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
trailing: const Icon(
Icons.arrow_forward_ios,
size: 18,
color: Color(0xff303030),
),
),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
width: 2.0,
color: Color(0xffcfd8dc),
),
),
),
),
),
);
}
虽然我认为您的代码应该可以工作,但如果在对 super
的调用完成之前完成,在 initState
中使用异步函数可能会导致麻烦。
首先,您是否将 JSON 文件作为资产添加到您的 pubspec.yaml
?
https://docs.flutter.dev/development/ui/assets-and-images
其次,为了防止出现异步问题,我会在您的 Widget 中使用 FutureBuilder
(您甚至可以使其成为无状态的)。
Widget build(BuildContext context) {
return FutureBuilder<Map<String, dynamic>>(
future: readJson(),
builder: (BuildContext context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
Map<String, dynamic> data = snapshot.data ?? {};
return MyAwesomeViewWithJsonData(data: data);
}
);
}