I am working with flutter for the first time and having issues understanding why my data will not show. For context, the API returns a list of (physical) libraries and their current occupancy. I have correctly implemented an API get request, got the data outputted in the terminal (printed) and thus I know my API call is working. I also implemented the data received from the JSON as a list using my data model, and then I created a body with the library name and occupancy as a ListTile. Nothing is shown when compiled on the device screen, just a blank screen, no circular progress indicator either.
Here is my home page:
import 'package:flutter/material.dart';
import '../models/post.dart';
import '../services/remote_service.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// Declare a list of Libraries
List<Libraries> _libraries = [];
@override
void initState() {
super.initState();
// Call the getPosts function when the HomePage is initialized
_getPosts();
}
// Function to make the GET request and store the response in a list of Libraries
void _getPosts() async {
var api = getDataAPI();
var librariesJson = await api.getPosts();
// Use the librariesFromJson function to convert the JSON string to a list of Libraries
setState(() {
_libraries = librariesFromJson(librariesJson!) as List<Libraries>;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Library Occupancy'),
),
body: _libraries == null
? const Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemCount: _libraries.length,
itemBuilder: (context, index) {
// Display the library name and occupancy in a ListTile
return ListTile(
title: Text(_libraries[index].webster.occupancy),
subtitle:
Text(_libraries[index].webster.lastRecordTime.toString()),
);
},
),
);
}
}
Here is my API request code (remote_service.dart):
// ignore_for_file: camel_case_types
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:xconcordia/models/post.dart';
class getDataAPI {
Future<String?> getPosts() async {
var credentials = '520:276377ba5206683e51d50fb86c378dc5';
// Encode the credentials in base64 format
var base64Credentials = base64Encode(utf8.encode(credentials));
var headers = {'Authorization': 'Basic $base64Credentials'};
var request = http.Request('GET',
Uri.parse('https://opendata.concordia.ca/API/v1/library/occupancy/'));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
String json = await response.stream.bytesToString();
// ignore: await_only_futures
Libraries library = await librariesFromJson(json);
print("webster: " library.webster.occupancy);
return library.webster.occupancy;
} else {
print(response.statusCode);
}
return null;
}
}
And finally, here is my JSON data model:
import 'dart:convert';
Libraries librariesFromJson(String str) => Libraries.fromJson(json.decode(str));
String librariesToJson(Libraries data) => json.encode(data.toJson());
class Libraries {
Libraries({
required this.webster,
required this.vanier,
required this.greyNuns,
});
GreyNuns webster;
GreyNuns vanier;
GreyNuns greyNuns;
factory Libraries.fromJson(Map<String, dynamic> json) => Libraries(
webster: GreyNuns.fromJson(json["Webster"]),
vanier: GreyNuns.fromJson(json["Vanier"]),
greyNuns: GreyNuns.fromJson(json["GreyNuns"]),
);
Map<String, dynamic> toJson() => {
"Webster": webster.toJson(),
"Vanier": vanier.toJson(),
"GreyNuns": greyNuns.toJson(),
};
}
class GreyNuns {
GreyNuns({
required this.occupancy,
required this.lastRecordTime,
});
String occupancy;
DateTime lastRecordTime;
factory GreyNuns.fromJson(Map<String, dynamic> json) => GreyNuns(
occupancy: json["Occupancy"],
lastRecordTime: DateTime.parse(json["LastRecordTime"]),
);
Map<String, dynamic> toJson() => {
"Occupancy": occupancy,
"LastRecordTime": lastRecordTime.toIso8601String(),
};
}
Also, when I run this code, here is the terminal output:
Performing hot restart...
Restarted application in 302ms.
flutter: webster: .0000
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: FormatException: Unexpected character (at character 1)
.0000
^
#0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
#1 _ChunkedJsonParser.parseNumber (dart:convert-patch/convert_patch.dart:1250:9)
#2 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:915:22)
#3 _parseJson (dart:convert-patch/convert_patch.dart:35:10)
#4 JsonDecoder.convert (dart:convert/json.dart:612:36)
#5 JsonCodec.decode (dart:convert/json.dart:216:41)
#6 librariesFromJson (package:xconcordia/models/post.dart:3:68)
#7 _HomePageState._getPosts.<anonymous closure> (package:xconcordia/views/home_page.dart:28:20)
#8 State.setState (package:flutter/src/widgets/framework.dart:1114:30)
#9 _HomePageState._getPosts (package:xconcordia/views/home_page.dart:27:5)
<asynchronous suspension>
CodePudding user response:
Modify Your Model Class
convert the data to String in modal class :
factory GreyNuns.fromJson(Map<String, dynamic> json) => GreyNuns(
occupancy: json["Occupancy"].toString(),
lastRecordTime: DateTime.parse(json["LastRecordTime"].toString()),
);