[英]How can I get data from a local json file and create a gridview in Flutter?
I'm trying to make an educational application in Turkish and i want to list the topics on my homepage.我正在尝试用土耳其语制作教育应用程序,我想在我的主页上列出主题。 I created a sketch of my homepage and i want to print the texts inside the cards by taking the parts named "konuBasligi" from the local json file.
我创建了主页的草图,我想通过从本地 json 文件中获取名为“konuBasligi”的部分来打印卡片内的文本。
Before sharing the codes, I would like to share the existing design and json file with you:在分享代码之前,我想和大家分享一下现有的设计和json文件:
{
"bende": {
"dersler": [{
"id": 0,
"dersAdi": "Türkçe"
}, {
"id": 1,
"dersAdi": "Matematik"
}, {
"id": 2,
"dersAdi": "Tarih",
"konular": [{
"konuId": 0,
"konuBasligi": "İslamiyet Öncesi Türk Tarihi",
"altkonular": [{
"altKonuId": 0,
"altKonuBasligi": "Giriş",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "Türk Adının Anlamı"
}, {
"baslikId": 1,
"baslikAdi": "İlk Yerleşim Yerleri"
}, {
"baslikId": 2,
"baslikAdi": "Göçler"
}]
}, {
"altKonuId": 1,
"altKonuBasligi": "İlk Türk Toplulukları ve Devletleri",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "İskitler"
}, {
"baslikId": 1,
"baslikAdi": "Asya Hun Devleti"
}, {
"baslikId": 2,
"baslikAdi": "Avrupa Hun Devleti"
}]
}, {
"altKonuId": 2,
"altKonuBasligi": "Diğer Türk Toplulukları ve Devletleri",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "Avatarlar"
}, {
"baslikId": 1,
"baslikAdi": "Karluklar"
}, {
"baslikId": 2,
"baslikAdi": "Kırgızlar"
}]
}, {
"altKonuId": 3,
"altKonuBasligi": "Kültür ve Medeniyet",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "Hükümdarlar"
}, {
"baslikId": 1,
"baslikAdi": "Devlet Yönetimi"
}, {
"baslikId": 2,
"baslikAdi": "Ordu"
}]
}]
}, {
"konuId": 1,
"konuBasligi": "İlk Türk İslam Devletleri"
}, {
"konuId": 2,
"konuBasligi": "Türkiye Tarihi"
}, {
"konuId": 3,
"konuBasligi": "Osmanlı Tarihi"
}, {
"konuId": 4,
"konuBasligi": "Kurtuluş Savaşı"
}, {
"konuId": 5,
"konuBasligi": "Çağdaş Türk ve Dünya Tarihi"
}]
}, {
"id": 3,
"dersAdi": "Coğrafya"
}, {
"id": 4,
"dersAdi": "Vatandaşlık"
}, {
"id": 5,
"dersAdi": "Genel Kültür"
}, {
"id": 6,
"dersAdi": "Program Geliştirme"
}, {
"id": 7,
"dersAdi": "Rehberlik ve Özel Eğitim"
}, {
"id": 8,
"dersAdi": "Öğretim Yöntem ve Teknikleri"
}, {
"id": 9,
"dersAdi": "Ölçme ve Değerlendirme"
}, {
"id": 10,
"dersAdi": "Öğrenme Psikolojisi"
}, {
"id": 11,
"dersAdi": "Gelişim Psikolojisi"
}]
}
}
I think I read the data using "FutureBuilder" and "DefaultAssetBundle" from the video I watched and the articles I read, but I got stuck in the "children" part in "Gridview.count".我想我从观看的视频和阅读的文章中使用“FutureBuilder”和“DefaultAssetBundle”读取了数据,但我陷入了“Gridview.count”中的“children”部分。 I couldn't adapt it myself because they usually use "Listview.builder".
我无法自己调整它,因为他们通常使用“Listview.builder”。
The code of the design image I shared contains too many files such as "screens", "utils".我分享的设计图片的代码包含太多的文件,例如“screens”、“utils”。 For this, I created a file with only the parts related to my question and its contents are as follows:
为此,我创建了一个文件,其中仅包含与我的问题相关的部分,其内容如下:
import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(
title: const Text('Gridview From JSON'),
),
body: FutureBuilder(
future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
builder: (context, snapshot) {
var read = json.decode(snapshot.data.toString());
return GridView.count(
crossAxisCount: 2,
padding:
const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
),
],
);
}),
),
);
}
}
Thank you in advance for your help...预先感谢您的帮助...
I Just spent some time on your question to recreate the example.我刚刚在您的问题上花了一些时间来重新创建示例。
Step1 : You need to convert the JSON to a model, which Can be done with the help of https://app.quicktype.io/ and save it as model.dart
Step1 : 您需要将 JSON 转换为模型,这可以在https://app.quicktype.io/的帮助下完成并保存为
model.dart
// model.dart
// To parse this JSON data, do
//
// final reportData = reportDataFromJson(jsonString);
import 'dart:convert';
import 'package:flutter/material.dart';
ReportData reportDataFromJson(String str) =>
ReportData.fromJson(json.decode(str));
String reportDataToJson(ReportData data) => json.encode(data.toJson());
class ReportData {
ReportData({
this.bende,
});
Bende? bende;
factory ReportData.fromJson(Map<String, dynamic> json) => ReportData(
bende: Bende.fromJson(json["bende"]),
);
Map<String, dynamic> toJson() => {
"bende": bende!.toJson(),
};
}
class Bende {
Bende({
this.dersler,
});
List<Dersler>? dersler;
factory Bende.fromJson(Map<String, dynamic> json) => Bende(
dersler:
List<Dersler>.from(json["dersler"].map((x) => Dersler.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"dersler": List<dynamic>.from(dersler!.map((x) => x.toJson())),
};
}
class Dersler {
Dersler({
this.id,
this.dersAdi,
this.konular,
});
int? id;
String? dersAdi;
List<Konular>? konular;
factory Dersler.fromJson(Map<String, dynamic> json) => Dersler(
id: json["id"],
dersAdi: json["dersAdi"],
konular: json["konular"] == null
? null
: List<Konular>.from(
json["konular"].map((x) => Konular.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"dersAdi": dersAdi,
"konular": konular == null
? null
: List<dynamic>.from(konular!.map((x) => x.toJson())),
};
}
class Konular {
Konular({
this.konuId,
this.konuBasligi,
this.altkonular,
});
int? konuId;
String? konuBasligi;
List<Altkonular>? altkonular;
factory Konular.fromJson(Map<String, dynamic> json) => Konular(
konuId: json["konuId"],
konuBasligi: json["konuBasligi"],
altkonular: json["altkonular"] == null
? null
: List<Altkonular>.from(
json["altkonular"].map((x) => Altkonular.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"konuId": konuId,
"konuBasligi": konuBasligi,
"altkonular": altkonular == null
? null
: List<dynamic>.from(altkonular!.map((x) => x.toJson())),
};
}
class Altkonular {
Altkonular({
this.altKonuId,
this.altKonuBasligi,
this.basliklar,
});
int? altKonuId;
String? altKonuBasligi;
List<Basliklar>? basliklar;
factory Altkonular.fromJson(Map<String, dynamic> json) => Altkonular(
altKonuId: json["altKonuId"],
altKonuBasligi: json["altKonuBasligi"],
basliklar: List<Basliklar>.from(
json["basliklar"].map((x) => Basliklar.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"altKonuId": altKonuId,
"altKonuBasligi": altKonuBasligi,
"basliklar": List<dynamic>.from(basliklar!.map((x) => x.toJson())),
};
}
class Basliklar {
Basliklar({
this.baslikId,
this.baslikAdi,
});
int? baslikId;
String? baslikAdi;
factory Basliklar.fromJson(Map<String, dynamic> json) => Basliklar(
baslikId: json["baslikId"],
baslikAdi: json["baslikAdi"],
);
Map<String, dynamic> toJson() => {
"baslikId": baslikId,
"baslikAdi": baslikAdi,
};
}
Step2 : Create a class to get Data from the model, something like Step2 :创建一个类以从模型中获取数据,例如
class DataFromReport {
static Future<ReportData> getDataLocally(BuildContext context) async {
final assetBundle = DefaultAssetBundle.of(context);
final data = await assetBundle.loadString('data/veri.json');
final reportData = reportDataFromJson(data);
return reportData;
}
}
Step3 : Create a method to get the list of "konuBasligi" from ReportData Step3 : 创建一个从 ReportData 中获取“konuBasligi”列表的方法
//getting list of konular from ReportData
List<String> getkonular(ReportData? data) {
List<String> listkonular = [];
//konular is not present in all dersler
// so fist get the length of dersler
int length = data?.bende?.dersler?.length ?? 0;
for (var i = 0; i < length; i++) {
final ders = data?.bende?.dersler?.elementAt(i);
//now get the number of konular
int length2 = ders?.konular?.length ?? 0;
for (var j = 0; j < length2; j++) {
final konu = ders?.konular?.elementAt(j);
listkonular.add(konu?.konuBasligi ?? '');
// print(konu?.konuBasligi);
}
}
return listkonular;
}
Step4 : Finally display the items in GridView using FutureBuilder<ReportData>
Step4 : 最后使用
FutureBuilder<ReportData>
在 GridView 中显示项目
FutureBuilder<ReportData>(
future: DataFromReport.getDataLocally(context),
builder: (context, snapshot) {
final data = snapshot.data;
final List<String> list = getkonular(data);
return GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.only(
left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: List.generate(list.length, (index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
child: Center(
child: Text(list[index],
style: const TextStyle(
fontSize: 20,
color: Colors.white,
))));
}));
}),
main.dart
full code. main.dart
完整代码。
import 'package:flutter/material.dart';
import 'package:get_local_json_data/model.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(
title: const Text('Gridview From JSON'),
),
body: FutureBuilder<ReportData>(
future: DataFromReport.getDataLocally(context),
builder: (context, snapshot) {
final data = snapshot.data;
final List<String> list = getkonular(data);
return GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.only(
left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: List.generate(list.length, (index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
child: Center(
child: Text(list[index],
style: const TextStyle(
fontSize: 20,
color: Colors.white,
))));
}));
}),
));
}
}
//getting list of konular from ReportData
List<String> getkonular(ReportData? data) {
List<String> listkonular = [];
//konular is not present in all dersler
// so fist get the length of dersler
int length = data?.bende?.dersler?.length ?? 0;
for (var i = 0; i < length; i++) {
final ders = data?.bende?.dersler?.elementAt(i);
//now get the number of konular
int length2 = ders?.konular?.length ?? 0;
for (var j = 0; j < length2; j++) {
final konu = ders?.konular?.elementAt(j);
listkonular.add(konu?.konuBasligi ?? '');
// print(konu?.konuBasligi);
}
}
return listkonular;
}
class DataFromReport {
static Future<ReportData> getDataLocally(BuildContext context) async {
final assetBundle = DefaultAssetBundle.of(context);
final data = await assetBundle.loadString('data/veri.json');
final reportData = reportDataFromJson(data);
return reportData;
}
}
Hope this will be helpful for you.希望这对您有所帮助。
Actually you have to check for state before trying to use data in future builder.实际上,在尝试在未来的构建器中使用数据之前,您必须检查状态。 Try these -
试试这些——
FutureBuilder(
future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
builder: (ctx, snapshot) {
// Checking if future is resolved
if (snapshot.connectionState == ConnectionState.done) {
// If we got an error
if (snapshot.hasError) {
return Center(
child: Text(
'${snapshot.error} occured',
style: TextStyle(fontSize: 18),
),
);
// if we got our data
} else if (snapshot.hasData) {
// Extracting data from snapshot object
var read = json.decode(snapshot.data.toString());
return GridView.count(
crossAxisCount: 2,
padding:
const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
),
],
);
}
}
),
Hope it helps.希望能帮助到你。
First Option: is to continue using GridView.count()
and for the children
you have to just iterate on them in any method, maybe for
loop or .map()
method.第一个选项:是继续使用
GridView.count()
并且对于children
,您必须以任何方法迭代它们,可能for
循环或.map()
方法。
Let's say you will display the dersler
read from the JSON file and you have created a variable to point on them like the following:假设您将显示从 JSON 文件中读取的
dersler
,并且您已经创建了一个变量来指向它们,如下所示:
var read = json.decode(snapshot.data.toString());
final List dersler = read['dersler'];
Now you can generate the children by iterating over the data,现在您可以通过迭代数据来生成孩子,
Example using .map()
method:使用
.map()
方法的示例:
children: dersler.map((item) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
);
}).toList(),
Example using for
loop:使用
for
循环的示例:
children: [
for (int i = 0; i < dersler.length; i++)
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
)
],
Second Option (Suggested): is to use GridView.builder()
instead of using GridView.count()
which gives you a bonus of lazy-loading the data into memory, which means only the data that is currently visible on the screen would be held in the memory, which is a very good optimization made out of the box by Flutter.第二个选项(建议):是使用
GridView.builder()
而不是使用GridView.count()
这给你一个延迟加载数据到内存的奖励,这意味着只有当前在屏幕上可见的数据才会是保存在内存中,这是 Flutter 开箱即用的一个非常好的优化。
Example:例子:
FutureBuilder(
future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
builder: (context, snapshot) {
var read = json.decode(snapshot.data.toString());
final List dersler = read['dersler'];
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
padding: const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: dersler.length,
itemBuilder: (BuildContext context, int index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
);
},
);
},
),
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.