Getting this error - type 'Future<dynamic>' is not a subtype of type 'List<dynamic>' - flutter

Whenever trying to call future data and trying converting to List, it returns the error
type 'Future' is not a subtype of type 'List'
Tried type-casting, but no help
On HomePage.dart
final getPost = NetworkFile().getPosts();
List posts;
void getPostsList() {
setState(() {
var res = getPost;
posts = res as List<dynamic>;
print(posts);
});
}
On Network.dart
class NetworkFile{
Future<dynamic> getPosts() async {
var response = await http.get('$kBlogURL' + 'posts?_embed');
Iterable resBody = await jsonDecode(response.body.toString());
return resBody;
}
}

You are decoding the response and its a List of type dynamic. There are few method to handle it. You can create a simple PODO class and cast/mapped to it. Or just do like below:
List posts = [];
void getPostsList() async {
final fetchedPosts = await NetworkFile().getPosts();
setState(() {
posts = fetchedPosts;
});
print(posts);
}
Here is a nice article about PODO.

final getPost = NetworkFile().getPosts();
Map posts;
void getPostsList() async {
var res = await getPost;
setState(() {
posts = res as Map<String, dynamic>;
print(posts);
});
}
class NetworkFile {
Future<dynamic> getPosts() async {
var response = await http.get('https://onetechstop.net/wp-json/wp/v2');
var resBody = await jsonDecode(response.body.toString());
return resBody;
}
}

Related

Future not waiting to resolve before next then Flutter Dart

I'm trying to return a list of values.
Assessing by using Late
late List userLikes = userListLikes.getUsersLikes();
My Code:
class GetUserLikes {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final user = FirebaseAuth.instance.currentUser!;
List getUsersLikes() {
try {
print('start');
final docRef = _firestore.collection("user_details").doc(user.uid);
docRef.get().then((DocumentSnapshot doc) async {
final data = doc.data() as Map<String, dynamic>;
print("data[user_likes]");
print(data['user_likes']);
print('end');
return await data['user_likes']; // → not awaiting
},
onError: (e) => print("Error getting document: $e"),
);
} catch (err) {
print('There was an error');
}
return ['Nothing Returned'];
}
}
The function is not completing and returns before the await has finished which is not the array I need.
start
[Nothing Returned] (Returns without completing)
data[user_likes]
[967, 769, 887, 820, 860, 833, 857, 1017] → The Array I want returned
end
As someone downvoted this answer here is the full working code:
This get an Array field from a Firestone database and then returns a list dynamic.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class GetUserLikes {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final user = FirebaseAuth.instance.currentUser!;
Future<List> getUsersLikes() async {
// Get the list of user likes from the Firestone Database and then
// return the list so it will only show the users likes on the profile page.
try {
final docRef = _firestore.collection("user_details").doc(user.uid);
DocumentSnapshot doc = await docRef.get(); // Await
final data = doc.data() as Map<String, dynamic>;
return data['user_likes'];
} catch (err) {
print('There was an error');
}
return ['Nothing Returned'];
}
Future<List> getLikes() async {
// Takes the Future<List> and turns it into a List<dynamic>
Future<List> userLikes = getUsersLikes();
List list = await userLikes;
return list; // Returns List<dynamic>
}
}
Then on the receiving Future builder it will have to be awaited.
GetUserLikes userLikesList = GetUserLikes();
List userLikes = await userLikesList.getLikes();

How to get value from Future in flutter

I'm trying to make a currency converter app in flutter.
The process I've planned was..
At the initState, get current currency data from API
Get currency data and assign it to 'currentCur'
Calculate converted currency value with 'currentCur' and display the value
But, I got an error that since 'currentCur' is Instance of 'Future<dynamic' so it can't calculated cause it is not subtype of 'num'
How can I get just value from Future in initState?
class _ConverterWidgetState extends State<ConverterWidget> {
late final TextEditingController _current;
late final currentCur;
late final currency;
fetchData() async {
try {
http.Response response = await http.get(
Uri.parse(
'https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD',
),
);
String jsonData = response.body;
var basePrice = jsonDecode(jsonData)[0]['basePrice'];
devtools.log(basePrice.toString());
return basePrice;
} catch (e) {
devtools.log(e.toString());
}
}
getCurrency(a) async {
return await Future.value(a);
}
#override
void initState() {
super.initState();
_current = TextEditingController(text: 1000.toString());
currentCur = fetchData();
devtools.log(currentCur.toString());
}
Specify the function is going to return a value with the "Future" keyWord
Future<num> fetchData() async {
var basePrice = 0;
try {
http.Response response = await http.get(
Uri.parse(
'https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD',
),
);
String jsonData = response.body;
basePrice = jsonDecode(jsonData)[0]['basePrice'];
devtools.log(basePrice.toString());
} catch (e) {
devtools.log(e.toString());
}
return basePrice;
}
void updateCurrentCur ()async{
var basePrice = await fetchData();
setState(() {
currentCur = basePrice;
});
}
#override
void initState() {
super.initState();
updateCurrentCur()
}

Flutter - Firstore returns null data even when data is there

I have the data which stored in firestore database. But when I try to fetch the data it returns null.
Here is the code,
Future<Map<String, dynamic>> getDocumentInfo(String collectionName, String docId) async {
DocumentSnapshot document = await FirebaseFirestore.instance.collection(collectionName).doc(docId).get();
print(document.data());
Map<String, dynamic> docInfo = document.data() as Map<String, dynamic>;
return docInfo;
}
Can anyone say what is the error? It gives the error "_CastError (type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast)"
Check if something related to this works ... it's not a snapshot but it'll give you the idea.
Future<void> addNewQuestion(Map AddQuestionData, File image) async {
CommanDialog.showLoading();
var pathimage = image.toString();
var temp = pathimage.lastIndexOf('/');
var result = pathimage.substring(temp + 1);
final ref = FirebaseStorage.instance.ref().child('').child(result);
var response = await ref.putFile(image);
var imageUrl = await ref.getDownloadURL();
CommanDialog.hideLoading();
try {
CommanDialog.showLoading();
var response = await firebaseInstance.collection('QuestionList').add({
'QuestionId': AddQuestionData['QuestionId'],
'QuestionText': AddQuestionData['QuestionText'],
"QuestionImageURL": imageUrl,
'AnswerA': AddQuestionData['AnswerA'],
"AnswerB": AddQuestionData['AnswerB'],
"AnswerC": AddQuestionData['AnswerC'],
"AnswerD": AddQuestionData['AnswerD'],
"AskedIn": AddQuestionData['AskedIn'],
"SubjectName": AddQuestionData['SubjectName'],
"ChapterName": AddQuestionData['ChapterName'],
"CorrectAnswer": AddQuestionData['CorrectAnswer'],
});
CommanDialog.hideLoading();
Get.back();
} catch (exception) {
CommanDialog.hideLoading();
}
}

How to cast dynamic to T or List<T>

I have a service to call api and some methods expects just Object and the rest expects list of objects. And I'm trying some tricks with generics but then errors in _get method with casting occurs.
// List
Future<List<ToDo>> getToDos() async {
final List<Map<String, dynamic>> response =
await _get<List<Map<String, dynamic>>>(url: "ToDos");
final List<ToDo> result =
response.map((data) => ToDo.fromJson(data)).toList();
return result;
//Object
Future<ToDo> getToDo() async {
final Map<String, dynamic> response =
await _get<Map<String, dynamic>>(url: "ToDo");
final ToDo result = ToDo.fromJson(response);
return result;
}
Future<T> _get<T>({
required String url,
}) async {
final Response response = await get(
Uri.https(_apiURL, url),
);
if (response.statusCode == 200) {
final T jsonResponse = json.decode(response.body) as T;
return jsonResponse;
} else {
throw Exception(response.body);
}
}
Error:
Exception has occurred. _CastError (type 'List<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>' in type cast)
Is it even possible to solve it like I'm trying?
[Update]:
Solution:
Future<T> _get<T, K>({
required String url,
}) async {
final Response response = await get(
Uri.https(_apiURL, url),
);
if (response.statusCode == 200) {
final dynamic jsonResponse = json.decode(response.body);
if (jsonResponse is List) {
return List<K>.from(jsonResponse) as T;
} else {
return jsonResponse as T;
}
} else {
throw Exception(response.body);
}
}
There's a list function called cast. You can cast a dynamic list to List<Map<String, dynamic>> like this:
final aList=[]//your list;
final castedList=aList.cast<Map<String, dynamic>>();

A value of type can't be returned from method because it has a return type of

List<String> getData() async {
var response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
print(data);
var temperature = jsonDecode(data)['main']['temp'];
var condition = jsonDecode(data)['weather'][0]['id'];
var city_name = jsonDecode(data)['name'];
return [temperature, condition, city_name];
} else {
print(response.statusCode);
}
}
}
I get a strange error saying that I can't return List<String> because is expecting List<String> to be returned.
Since the function get data is is async it should return Future<List<String>> example is as follows:
Future<List<String>> getData() async {
var response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
print(data);
var temperature = jsonDecode(data)['main']['temp'];
var condition = jsonDecode(data)['weather'][0]['id'];
var city_name = jsonDecode(data)['name'];
return <String>[temperature, condition, city_name];
} else {
print(response.statusCode);
}
}
Also your are decoding 3 times unnecessarily, you can do it once keep it in var and use for further usage, example as follows:
String data = response.body;
var decodedData = jsonDecode(data);
var temperature = decodedData['main']['temp'];
var condition = decodedData['weather'][0]['id'];
var city_name = decodedData['name'];
As a generalization, when you get this error in an async function:
A value of type x can't be returned from method because it has a
return type of x
The message seems weird, but it could mean that you are missing a Future<> return type.
So add Future<> to your method return type:
Example:
List<String> getValues() async
{
List<String> list = await getJson();
return list;
}
Change to:
Future<List<String>> getValues() async
{
List<String> list = await getJson();
return list;
}