Flutter newbie here! I'm trying to build a list view from an api response.
I am getting a JSON response:
{
"data": [
{
"id": "102",
"operator_id": "Airtel",
"circle_id": "Andhra Pradesh",
"recharge_amount": "10",
"recharge_talktime": "7.47",
"recharge_validity": "N.A.",
"recharge_short_desc": "Recharge of Rs. 10 by Airtel",
"recharge_long_desc": "Talktime: Rs.7.47",
"recharge_type": "Top up",
"updated_at": "02-06-2022 11:27:02"
},
{
"id": "103",
"operator_id": "Airtel",
"circle_id": "Andhra Pradesh",
"recharge_amount": "20",
"recharge_talktime": "14.95",
"recharge_validity": "N.A.",
"recharge_short_desc": "Recharge of Rs. 20 by Airtel",
"recharge_long_desc": "Talktime: Rs.14.95",
"recharge_type": "Top up",
"updated_at": "02-06-2022 11:27:02"
},
{
"id": "105",
"operator_id": "Airtel",
"circle_id": "Andhra Pradesh",
"recharge_amount": "100",
"recharge_talktime": "81.75",
"recharge_validity": "N.A.",
"recharge_short_desc": "Recharge of Rs. 100 by Airtel",
"recharge_long_desc": "Talktime: Rs.81.75",
"recharge_type": "Top up",
"updated_at": "02-06-2022 11:27:02"
},
{
"id": "106",
"operator_id": "Airtel",
"circle_id": "Andhra Pradesh",
"recharge_amount": "500",
"recharge_talktime": "423.73",
"recharge_validity": "N.A.",
"recharge_short_desc": "Recharge of Rs. 500 by Airtel",
"recharge_long_desc": "Talktime: Rs.423.73",
"recharge_type": "Top up",
"updated_at": "02-06-2022 11:27:02"
}
]
}
I use this Model Class to convert JSON to Dart Objects:
Plans plansFromJson(String str) => Plans.fromJson(json.decode(str));
String plansToJson(Plans data) => json.encode(data.toJson());
class Plans {
Plans({
required this.data,
});
List<Datum> data;
factory Plans.fromJson(Map<String, dynamic> json) => Plans(
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
required this.id,
required this.operatorid,
required this.circleid,
required this.rechargeAmount,
required this.rechargeTalktime,
required this.rechargeValidity,
required this.rechargeShortdesc,
required this.rechargeLongdesc,
required this.rechargeType,
required this.updatedAt,
});
String id;
String operatorid;
String circleid;
String rechargeAmount;
String rechargeTalktime;
String rechargeValidity;
String rechargeShortdesc;
String rechargeLongdesc;
String rechargeType;
String updatedAt;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
operatorid: json["operatorid"],
circleid: json["circleid"],
rechargeAmount: json["recharge_amount"],
rechargeTalktime: json["recharge_talktime"],
rechargeValidity: json["recharge_validity"],
rechargeShortdesc: json["recharge_shortdesc"],
rechargeLongdesc: json["recharge_longdesc"],
rechargeType: json["recharge_type"],
updatedAt: json["updated_at"],
);
Map<String, dynamic> toJson() => {
"id": id,
"operatorid": operatorid,
"circleid": circleid,
"recharge_amount": rechargeAmount,
"recharge_talktime": rechargeTalktime,
"recharge_validity": rechargeValidity,
"recharge_shortdesc": rechargeShortdesc,
"recharge_longdesc": rechargeLongdesc,
"recharge_type": rechargeType,
"updated_at": updatedAt,
};
}
API Request Method:
Future<Plans> getPlanDetails(
String operator, String circle, String rechargeType) async {
var planUrl = Uri.parse(
'https://api.datayuge.com/v6/rechargeplans/?apikey=$datayugeApiKey&operator_id=$operator&circle_id=$circle&recharge_type=$rechargeType&limit=50&order_by=recharge_amount');
debugPrint(planUrl.toString());
final response = await http.get(planUrl);
debugPrint(response.body);
String jsonString = response.body;
final plans = plansFromJson(jsonString);
return plans;
}
When I try to build a listview from this data, I get the LateInitializationError. Everything works fine when I load a local String as JSON. I get this error only when I'm fetching the data from API.
Stateful Widget:
class RechargePlansView extends StatefulWidget {
RechargePlansView({Key? key}) : super(key: key);
@override
State<RechargePlansView> createState() => _RechargePlansViewState();
}
class _RechargePlansViewState extends State<RechargePlansView> {
List<Datum> data = [];
late Plans plans;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Recharge Plans')),
body: Text('Recharge Plans view'),
ListView.builder(
itemCount: widget.plans.data.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
radius: 28,
child: Center(
child: Text(
'\u{20B9}${plans.data[index].rechargeAmount.toString()}'),
),
),
title: Text(
'Talktime: ${plans.data[index].rechargeAmount} Validity: ${plans.data[index].rechargeValidity}'),
subtitle: Text(plans.data[index].rechargeShortDesc),
);
}),
);
}
}
CodePudding user response:
you defined: late Plans plans;
but which line you initialize this attribute?
also in which line you called api method?
actually your plans attr is null!
CodePudding user response:
I solved this by Initializing Plans in setState().
class _RechargePlansViewState extends State<RechargePlansView> {
@override
void initState() {
super.initState();
widget.getPlanDetails().then((value) {
setState(() {
plans = value;
});
});
}
}