I am getting an Unhandled Exception: type 'Null' is not a subtype of type 'FutureOr<List>' this error while fetching the data from the API. I know there are lot of solutions out there but they did not work for me.
and API is taking too much time to get load and sometimes it gets loaded very fast. I have provided the code below.
Future<List<dynamic>> getSubjects() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
var result = await http.get(
Uri.parse("xxxxxxxxxxxx"),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': "Bearer $token",
});
return jsonDecode(result.body)['result'];
}
FUTURE BUILDER CODE
Padding(
padding: const EdgeInsets.all(18.0),
child: FutureBuilder(
future: getSubjects(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data?.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
decoration: BoxDecoration(
image: const DecorationImage(
image: AssetImage('assets/bg.png'),
fit: BoxFit.cover,
),
color: Colors.amber[50],
borderRadius: BorderRadius.circular(10.0),
boxShadow: const [
BoxShadow(
color: Colors.grey,
blurRadius: 2.0,
offset: Offset(2.0, 2.0))
],
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
title: Text(
snapshot.data[index]['subject_name']
.toString(),
style: const TextStyle(color: Colors.white),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon((Icons.book),
color: Colors.amber.shade900),
const SizedBox(
width: 10.00,
),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
GiveFeedbackScreen(
subjectId: snapshot.data[index]
['subject_id'],
subjectName: snapshot.data[index]
['subject_name'],
feedbackId: widget.id,
),
),
);
},
),
],
),
),
),
);
},
);
} else {
return Center(
child: LinearProgressIndicator(
backgroundColor: Colors.amber[500]),
);
}
},
),
),
CodePudding user response:
Remove 'Content-Type': 'application/x-www-form-urlencoded',
.. not sure if a get request will need this content type
CodePudding user response:
write your function as Future<List<dynamic>>?
It will solve your issue
CodePudding user response:
I think it is better to accept null from future. Try like
Future<List<dynamic>?> getSubjects(){...}
And while
FutureBuilder<List<dynamic>?>(
builder: (context, snapshot) {
if(snapshot.hasData){}
CodePudding user response:
As your Future function is expecting some type of value as return and you are passing "null" value you get the Unhandled exception. What I do in this method is using the Try catch,
Future<List<dynamic>> getSubjects() async {
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
var result = await http.get(
Uri.parse("xxxxxxxxxxxx"),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': "Bearer $token",
});
return jsonDecode(result.body)['result'];
} catch (e) {
throw e;
}
}
And rest you can handle null value in the UI Component.
Hope this is what you are looking for :)