在Flutter Stateful Widget中从json加载数据时出现问题



从json加载数据时遇到了一些问题。我认为问题出在获取数据上。知道发生了什么事吗?

我不是最好的Flutter开发人员,这更像是一种爱好,所以尽量随和。

这里是错误:

以下NoSuchMethodError在构建RulesCard时抛出(dirty,依赖项:[LocalizationsScope-[GlobalKey#806d5],_InheritedTheme],状态:_RulesCardState#471f3(:在null上调用了getter"campsRulesList"。接收方:null尝试调用:campus规则列表

导致相关错误的小部件是:RulesCardfile:///H:/Projekty/kampus_sggw/lib/global_widgets/side_drawer.dart:43:57当抛出异常时,这是堆栈:#0 Object.noSuchMethod(dart:core-patch/Object_patch.dart:54:5(#1 _RulesCardState.build(包:kampus_sgw/screens/map_screen/rules_card.dart:69:53(#2 StatefulElement.build(包:flutter/src/widgets/framework。dart:4684:27(#3 ComponentElement.performRebuild(包:flutter/src/widgets/framework.dart:4567:15(#4 StatefulElement.performRebuild(包:flutter/src/widgets/framework.dart:4739:11(。。。════════════════════════════════════════════════════════════════════════════E/flutter(18750(:[错误:flutter/lib/ui_dart_state.cc(186(]未处理的异常:无法加载资产:assets/json/campus_rules_pl.json E/flutter(18750(:#0
PlatformAssetBundle.load(包:flutter/src/services/asset_bundle.dart:227:7(E/flutter(18750(:E/flutter(18750(包:flutter/src/services/asset_bundle.dart:68:27(E/flutter(18750(:E/flutter(18750年(:#2
_RulesCardState.loadFromJson(软件包:kampus_sgw/screens/map_screen/rules_card.dart:31:54(E/flutter(18750(:E/flutter(:#3
_RulesCardState.initState.(软件包:kampus_sgw/screens/map_screen/rules_card.dart:23:21(E/颤振(18750(:E/颤振

rules_card.dart其中定义了小部件:

class RulesCard extends StatefulWidget {
@override
_RulesCardState createState() => _RulesCardState();
}
class _RulesCardState extends State<RulesCard> {
CampusRules rulesListPL;
CampusRules rulesListEn;
@override
initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async
{
rulesListPL = await this.loadFromJson();
print(rulesListPL);
});
super.initState();
}
Future<CampusRules> loadFromJson() async {
Map<String, dynamic> campusRulesMap = jsonDecode(await CampusRules.getJsonSting());
final campusRules = CampusRules.fromJson(campusRulesMap);
return campusRules;
}
@override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
Container(
height: 90.0,
child: DrawerHeader(
child: Text(
LocaleKeys.campus_rules.tr(),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline3
),
decoration: BoxDecoration(
color: Theme.of(context).bannerTheme.backgroundColor
),
),
),
for (CampusRule campusRule in rulesListPL.campusRulesList)
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: buildListTitle(context, campusRule),
),
],
),
);
}
Widget buildListTitle(BuildContext context, CampusRule rule) => ExpansionTile(
title: Text(
rule.rule,
style: Theme.of(context).textTheme.headline4,
),
children: [
for (CampusSubRule subRule in rule.subRulesList)
ListTile(
title:
Text(
subRule.subRule,
style: Theme.of(context).textTheme.headline4,
),
)
],
);
}

campus_rules.dart其中定义了CampusRules对象的模型:

import 'package:flutter/services.dart';
import 'package:json_annotation/json_annotation.dart';
part 'campus_rules.g.dart';
@JsonSerializable()
class CampusRules {
String name;
String lang;
List<CampusRule> campusRulesList;
CampusRules(
this.name,
this.lang,
this.campusRulesList,
);
factory CampusRules.fromJson(Map<String, dynamic> json) =>
_$CampusRulesFromJson(json);
static Future<String> getJsonSting() {
return rootBundle.loadString('assets/json/campus_rules_pl.json');
}
}
@JsonSerializable()
class CampusRule {
int ruleNumber;
String rule;
List<CampusSubRule> subRulesList;
CampusRule(
this.ruleNumber,
this.rule,
this.subRulesList,
);
factory CampusRule.fromJson(Map<String, dynamic> json) =>
_$CampusRuleFromJson(json);
}
@JsonSerializable()
class CampusSubRule {
int subRuleNumber;
String subRule;
CampusSubRule(
this.subRuleNumber,
this.subRule,
);
factory CampusSubRule.fromJson(Map<String, dynamic> json) =>
_$CampusSubRuleFromJson(json);
}

campus_rules.g.dart其中是序列化的自动生成代码

// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'campus_rules.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
CampusRules _$CampusRulesFromJson(Map<String, dynamic> json) {
return CampusRules(
json['name'] as String,
json['lang'] as String,
(json['campusRulesList'] as List)
?.map((e) =>
e == null ? null : CampusRule.fromJson(e as Map<String, dynamic>))
?.toList(),
);
}
Map<String, dynamic> _$CampusRulesToJson(CampusRules instance) =>
<String, dynamic>{
'name': instance.name,
'lang': instance.lang,
'campusRulesList': instance.campusRulesList,
};
CampusRule _$CampusRuleFromJson(Map<String, dynamic> json) {
return CampusRule(
json['ruleNumber'] as int,
json['rule'] as String,
(json['subRulesList'] as List)
?.map((e) => e == null
? null
: CampusSubRule.fromJson(e as Map<String, dynamic>))
?.toList(),
);
}
Map<String, dynamic> _$CampusRuleToJson(CampusRule instance) =>
<String, dynamic>{
'ruleNumber': instance.ruleNumber,
'rule': instance.rule,
'subRulesList': instance.subRulesList,
};
CampusSubRule _$CampusSubRuleFromJson(Map<String, dynamic> json) {
return CampusSubRule(
json['subRuleNumber'] as int,
json['subRule'] as String,
);
}
Map<String, dynamic> _$CampusSubRuleToJson(CampusSubRule instance) =>
<String, dynamic>{
'subRuleNumber': instance.subRuleNumber,
'subRule': instance.subRule,
}; 

json文件:

{
"name": "campus_rules",
"lang": "pl",
"campusRulesList": [
{
"ruleNumber": "1",
"rule": "I. Kampus Uczelni jest terenem ogólnodostępnym w godz. od 6:00 do 22:00. W pozostałym przedziale czasowym na terenie Kampusu mogą przebywać tylko osob do tego uprawnione:",
"subRulesList": [
{
"subRuleNumber": "1",
"subRule": "1) pracownicy Uczelni (a także osoby im towarzyszące) oraz osoby wykonujące prace zlecone na rzecz Uczelni posiadające indywidualne zezwolenia;"
},
{
"subRuleNumber": "2",
"subRule": "2) studenci i doktoranci SGGW oraz osoby im towarzyszące;"
},
{
"subRuleNumber": "3",
"subRule": "3) mieszkańcy domów studenckich. Domu Asystenckiego i Pokoi Gościnnych Ikar;"
},
{
"subRuleNumber": "3",
"subRule": "4) osoby korzystające z obiektów usługowych na terenie Kampusu do czasu ich zamknięcia."
}
]
},
{
"ruleNumber": "2",
"rule": "II. Każdy kto przebywa na terenie Kampusu SGGW zobowiązany jest do:",
"subRulesList": [
{
"subRuleNumber": "1",
"subRule": "1) przestrzegania ogólnie przyjętych norm postępowania w zakresie relacji międzyludzkich:"
},
{
"subRuleNumber": "2",
"subRule": "2) przestrzegania zasad poszanowania mienia wspólnego Uczelni, poszanowania zieleni, a zwłaszcza niezaśmiecania Kampusu;"
},
{
"subRuleNumber": "3",
"subRule": "3) właściwego korzystania z urządzeń, instalacji oraz wyposażenia budynków z uwzględnieniem ich przeznaczenia;"
},
{
"subRuleNumber": "4",
"subRule": "4) właściwego korzystania z dróg transportu samochodowego, parkingów dla samochodów oraz chodników dla pieszych;"
},
{
"subRuleNumber": "5",
"subRule": "5) zachowania zwykłych i nakazanych środków ostrożności przy trzymaniu psów oraz przy trzymaniu innych zwierząt."
}
]
},
{
"ruleNumber": "3",
"rule": "III. Na terenie Kampusu zabrania się:",
"subRulesList": [
{
"subRuleNumber": "1",
"subRule": "1) zakłócania porządku publicznego, agresywnego, napastliwego i nieobyczajnego zachowania oraz niszczenia mienia Uczelni;"
},
{
"subRuleNumber": "2",
"subRule": "2) spożywania alkoholu (nie dotyczy lokali konsumpcyjnych znajdujących się na terenie Kampusu SGGW oraz wydarzeń okazjonalnych lub cyklicznych organizowanychna terenie Kampusu SGGW, pod warunkiem wyrażenia przez Władze Uczelni zgody na spożywanie alkoholu podczas takiego wydarzenia), przebywania w stanie nietrzeźwym oraz pod wpływem innych środków odurzających;"
},
{
"subRuleNumber": "3",
"subRule": "3) wnoszenia i posiadania broni (z wyłączeniem osób pełniących służbę ochrony) i innych przedmiotów mogących stanowić zagrożenie bezpieczeństwa, w szczególności: materiałów wybuchowych, wyrobów pirotechnicznych, środków odurzających lub psychotropowych;"
},
{
"subRuleNumber": "4",
"subRule": "4) organizowania ognisk;"
},
{
"subRuleNumber": "5",
"subRule": "5) grillowania poza miejscami do tego wyznaczonymi;"
},
{
"subRuleNumber": "6",
"subRule": "6) wyprowadzania psów bez smyczy i kagańców oraz pozastawiania ich bez opieki;"
},
{
"subRuleNumber": "7",
"subRule": "7) parkowania pojazdów poza wyznaczonymi miejscami;"
},
{
"subRuleNumber": "8",
"subRule": "8) prowadzenia handlu obwoźnego i akwizycji bez zgody Władz Uczelni."
}
]
},
{
"ruleNumber": "4",
"rule": "VII. Osoby odpowiedzialne za sprawowanie nadzoru na terenie Kampusu SGGW. a szczególnie pracownicy Straży Akademickiej oraz monitoringu obiektów są uprawnione i zobowiązane do:",
"subRulesList": [
{
"subRuleNumber": "1",
"subRule": "1) ograniczania wstępu na teren Kampusu osobom nieupoważnionym, a w przypadku ujawnienia naruszeń postanowień Regulaminu żądania opuszczenia terenu Kampusu;"
},
{
"subRuleNumber": "2",
"subRule": "2) zwracania szczególnej uwagi na osoby, które swoim zachowaniem budzą uzasadnione podejrzenia zakłócenia porządku publicznego i reagowania w sytuacjach zagrożenia;"
},
{
"subRuleNumber": "3",
"subRule": "3) współdziałania, zgodnie z Prawem o Szkolnictwie Wyższym i Statutem Uczelni, w zakresie bezpieczeństwa z właściwymi terenowo jednostkami Policji. Straży Miejskiej, a w przypadku jakiegokolwiek zagrożenia wezwania grup interwencyjnych czy innych służb miejskich lub ratunkowych (Straż Pożarna. Pogotowie Ratunkowe);"
},
{
"subRuleNumber": "4",
"subRule": "4) kontrolowania uprawnień do przebywania na terenie Kampusu SGGW."
}
]
}
]
}

您正在尝试访问rulesListPL,而无需等待loadFromJson()完成并将结果分配给它。因此,您需要一个加载状态:

@override
Widget build(BuildContext context) {
// If rulesListPL has not initialized yet
if (rulesListPL == null) {
// Display your loading screen instead
return Center(
child: CircularProgressIndicator(),
);
}
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
Container(
height: 90.0,
child: DrawerHeader(
child: Text(LocaleKeys.campus_rules.tr(),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline3),
decoration: BoxDecoration(
color: Theme.of(context).bannerTheme.backgroundColor),
),
),
for (CampusRule campusRule in rulesListPL.campusRulesList)
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: buildListTitle(context, campusRule),
),
],
),
);
}

感谢Stewie的回答,我添加了一些代码来处理加载后的刷新:

class _RulesCardState extends State<RulesCard> with TickerProviderStateMixin{
CampusRules rulesListPL;
CampusRules rulesListEn;
AnimationController controller;
@override
initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async
{
rulesListPL = await this.loadFromJson();
print(rulesListPL);
});
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 5),
)..addListener(() {
setState(() {});
});
controller.repeat(reverse: true);
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
Future<CampusRules> loadFromJson() async {
Map<String, dynamic> campusRulesMap = jsonDecode(await CampusRules.getJsonSting());
final campusRules = CampusRules.fromJson(campusRulesMap);
return campusRules;
}
@override
Widget build(BuildContext context) {
// If rulesListPL has not initialized yet
if (rulesListPL == null) {
// Display your loading screen instead
return Center(
child: CircularProgressIndicator(
value: controller.value,
),
);
}
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
Container(
height: 90.0,
child: DrawerHeader(
child: Text(
LocaleKeys.campus_rules.tr(),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline3
),
decoration: BoxDecoration(
color: Theme.of(context).bannerTheme.backgroundColor
),
),
),
for (CampusRule campusRule in rulesListPL.campusRulesList)
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: buildListTitle(context, campusRule),
),
],
),
);
}

最新更新