How to convert the type Future<List<T>> to <List<T>> in fultter? - flutter

everyone! I was developing e-commerce flutter app with doofinder APIs.
But I faced a thorny problem. I tried to get data from doofinder(it's just search service) API then present to screen. I added screen-shots.
Future<List<Product>> fetchProduct(query) async {
var response = await http.get(
Uri.parse(
'https://eu1-search.doofinder.com/5/search?hashid=30a5f&query=$query'),
// Send authorization headers to the backend.
headers: {'Authorization': 'c59dadc5d822ca2b134f170'},
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
print(jsonDecode(response.body)['results'].toList().runtimeType);
return jsonDecode(response.body)['results'].toList().cast<List<Product>>();
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
then,
onChanged: (_) => EasyDebounce.debounce(
'tFMemberController',
const Duration(milliseconds: 800),
() {
isSearchStarted =
textController!.text.isNotEmpty &&
textController!.text.trim().length > 0;
print('isSearchStarted $isSearchStarted');
if (isSearchStarted) {
print('${textController!.text.trim()}');
searchedProducts =
fetchProduct(textController!.text)
as List<Product>;
print(searchedProducts);
}
setState(() {});
},
),
And this is error log.
E/flutter ( 5295): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Future<List<Product>>' is not a subtype of type 'List<Product>' in type cast
E/flutter ( 5295): #0 _SearchPageState.build.<anonymous closure>.<anonymous closure> (package:s4s_mobileapp/search/page_search.dart:151:41)
E/flutter ( 5295): #1 EasyDebounce.debounce.<anonymous closure> (package:easy_debounce/easy_debounce.dart:44:22)
E/flutter ( 5295): #2 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter ( 5295): #3 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter ( 5295): #4 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter ( 5295): #5 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
E/flutter ( 5295):
I/flutter ( 5295): List<dynamic>
E/flutter ( 5295): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'CastList<dynamic, List<Product>>' is not a subtype of type 'FutureOr<List<Product>>'
E/flutter ( 5295): #0 fetchProduct (package:s4s_mobileapp/search/page_search.dart:41:58)
E/flutter ( 5295): <asynchronous suspension>
E/flutter ( 5295):
This makes me crazy.
I want you to take a closer look at the pictures below and find a suitable solution please.

Change
jsonDecode(response.body)['results'].toList().cast<List<Product>>();
to this:
jsonDecode(response.body)['results'].toList().cast<Product>();
The cast method already knows that you are working with lists and only wants to know the type of the elements, but not the type of the list itself.
EDIT: You also need to change:
searchedProducts = fetchProduct(textController!.text) as List<Product>;
to this:
searchedProducts = fetchProduct(textController!.text) as Future<List<Product>>;
You have to work with futures as your result is processed asynchronously. In the widget tree you have to use FutureBuilder which takes a future and builds your list as you want.

Related

Unhandled Exception: Connection reset by peer flutter

I make small app that app get data from api internet. its work but some time app lose connection with internet and I get this message error:
E/flutter ( 3931): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Connection reset by peer
E/flutter ( 3931): #0 IOClient.send (package:http/src/io_client.dart:88:7)
E/flutter ( 3931): <asynchronous suspension>
E/flutter ( 3931): #1 BaseClient._sendUnstreamed (package:http/src/base_client.dart:93:32)
E/flutter ( 3931): <asynchronous suspension>
E/flutter ( 3931): #2 _withClient (package:http/http.dart:164:12)
E/flutter ( 3931): <asynchronous suspension>
I'm use http library latest version.
SDK flutter 3.3.0 version.
Future fetchMain() async {
var response = await http.get(Uri.parse('https://************.php'));
if (response.statusCode == 200) {
final Data = json.decode(response.body).cast<Map<String, dynamic>>();
List<MainModel> ListData = Data.map<MainModel>(
(json) {
return MainModel.fromJson(json);
}).toList();
return ListData;
} else {
}
}
The connection remains disconnected from the Internet for about 3 minutes and then works again.
Anyone have idea about that problem and how I can solve it?
thank you.
Put a try-catch block in the fetchMain function and handle possible errors

How to turn part of the response from Dio into a variable in Flutter/Dart?

Using Dio, I make a specific request to the site:
final response = await Dio().get(
…
print(response); //Just to see my response
Here is the response from the console:
I/flutter ( 4594): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","Data":"11.5","App":"The Best App","Current":"98789fg43"}}]}
I am satisfied with the data. They are correct. For further work, I only need the recrNhzWnPdiSFaCs value. I want to pass it to a variable that will be used in another part of the code. How to do it?
Edit1.
Using var decodedString = json.decode(response.data.toString()); does not cause any errors in the code. But on startup, the following appears in the console:
I/flutter ( 4594): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","First":"11.5","App":"The Best App","Current":"98789fg43"}}]}
E/flutter ( 4594): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: FormatException: Unexpected character (at character 2)
E/flutter(4594): {records: [{id: recrNhzWnPdiSFaCs, createdTime: 2022-07-28T15:45:23.000Z, f...
E/flutter ( 4594): ^
E/flutter ( 4594):
E/flutter ( 4594): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
E/flutter ( 4594): #1 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:913:48)
E/flutter ( 4594): #2 _parseJson (dart:convert-patch/convert_patch.dart:35:10)
E/flutter ( 4594): #3 JsonDecoder.convert (dart:convert/json.dart:612:36)
E/flutter ( 4594): #4 JsonCodec.decode (dart:convert/json.dart:216:41)
E/flutter(4594): #5 _MainWidgetState.airtableFind(package:example/main.dart:214:32)
E/flutter ( 4594): <asynchronous suspension>
E/flutter ( 4594):
And here is the whole code in case I made a mistake somewhere:
//Airtable (find a record)
void airtableFind() async {
try {
final response = await Dio().get(
'https://api.airtable.com/v0/'+projectBase+'/'+recordName,
queryParameters: {
// 'filterByFormula': 'SEARCH("Cactus",{Name})' // Searches the value 'Cactus' in the {'Short description'} field.
'filterByFormula': 'SEARCH('+'"'+testName+'"'+',{Name})' // Searches the value 'Cactus' in the {'Short description'} field.
// 'filterByFormula': 'SEARCH('+testName+',{Name})' // Searches the value 'Cactus' in the {'Short description'} field.
},
options: Options(
contentType: 'Application/json',
headers: {
'Authorization': 'Bearer'+' '+apiKey,
'Accept': 'Application/json',
},
),
);
// TODO: Whatever you want to do with the response. A good practice is to transform it into models and than work with them
print(response);
// String fromString = response;
// String response1 = '{"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","Data":"11.5","App":"The Best App","Current":"98789fg43"}}]}';
var decodedString = json.decode(response.data.toString());
// final decodedJSON = json.decode(response.body);
// final decodedJSON = json.decode(utf8.decode(response.bodyBytes));
print(decodedString['records'][0]['id']);
String id = decodedString['records'][0]['id'];
} on DioError catch (e) {
// TODO: Error handling
if (e.response != null) {
// print(e.response.data);
print(e);
} else {
// print(e.request);
print(e.message);
}
}
}
Edit2. When I use final decodedString = json.decode(response.data); I see the following errors in the console:
I/flutter( 4289): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","First":"11.5","App":"The Best App","Current":"98789fg43"}}]}
E/flutter ( 4289): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
E/flutter(4289): #0 _MainWidgetState.airtableFind(package:example/main.dart:217:50)
E/flutter ( 4289): <asynchronous suspension>
When I use var decodedString = json.decode(response.data.toString()); the following errors appear in the console:
I/flutter( 4289): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","First":"11.5","App":"The Best App","Current":"98789fg43"}}]}
E/flutter ( 4289): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: FormatException: Unexpected character (at character 2)
E/flutter(4289): {records: [{id: recrNhzWnPdiSFaCs, createdTime: 2022-07-28T15:45:23.000Z, f...
E/flutter ( 4289): ^
E/flutter ( 4289):
E/flutter ( 4289): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
E/flutter ( 4289): #1 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:913:48)
E/flutter ( 4289): #2 _parseJson (dart:convert-patch/convert_patch.dart:35:10)
E/flutter ( 4289): #3 JsonDecoder.convert (dart:convert/json.dart:612:36)
E/flutter ( 4289): #4 JsonCodec.decode (dart:convert/json.dart:216:41)
E/flutter(4289): #5 _MainWidgetState.airtableFind(package:example/main.dart:217:32)
E/flutter ( 4289): <asynchronous suspension>
You can use json.decode to convert the response to a json value. Then you can fetch its values with respective keys like
String response = '{"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","Data":"11.5","App":"The Best App","Current":"98789fg43"}}]}';
var decodedString = json.decode(response);
print(decodedString['records'][0]['id']);
//Output : recrNhzWnPdiSFaCs
Don't miss to import
import 'dart:convert';
You can achieve your purpose by decoding your JSON.
final decodedJSON = json.decode(response.data);
, also if your response contains a UTF-8 encoding (has for example Persian characters), you can use:
final decodedJSON = json.decode(utf8.decode(response.bodyBytes));
dio body name is data so the decoding would be as following
final decodedJSON = json.decode(response.data);

Flutter get return empty body but it is not empty

as I wrote in the title I'm trying to obtain data from a server but the method http.get(Uri.parse(url)) returns empty body and od course the error caused by trying to decode an empty body,
But if I copy paste the url used before I can see the json content. How is it possible?
The function I'm using is:
Future getData ( ) async {
String url = 'http://www.viaggiatreno.it/viaggiatrenonew/resteasy/viaggiatreno/andamentoTreno/...';
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 204) {
var data = response.body;
print("data are : $data");
return jsonDecode(data);
} else {
print("unable to load data");
}
}
This is a little portion of what I should see with this command: print("data are : $data");
{
"tipoTreno":"PG",
"orientamento":"B",
"codiceCliente":1,
"fermateSoppresse":[
],
"dataPartenza":null,
"fermate":[
{
"orientamento":"B",
"kcNumTreno":null,
"stazione":"VENEZIA SANTA LUCIA",
"id":"S02593",
"listaCorrispondenze":null,
"programmata":1646663160000,
"programmataZero":null,
"effettiva":1646663160000,
"ritardo":0,
"partenzaTeoricaZero":1646663160000,
"arrivoTeoricoZero":null,
"partenza_teorica":1646663160000,
"arrivo_teorico":null,
"isNextChanged":false,
"partenzaReale":1646663160000,
"arrivoReale":null,
"ritardoPartenza":0,
"ritardoArrivo":0,
"\"pro ...........}"
so as you can see the body is what you want but not empty, and it is in json format.
Can anyone help me? I can't solve this issue.
Output is:
I/flutter (3177): data are:
E/flutter ( 3177): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: FormatException: Unexpected end of input (at character 1)
E/flutter ( 3177):
E/flutter ( 3177): ^
E/flutter ( 3177):
E/flutter ( 3177): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1405:5)
E/flutter ( 3177): #1 _ChunkedJsonParser.close (dart:convert-patch/convert_patch.dart:523:7)
E/flutter ( 3177): #2 _parseJson (dart:convert-patch/convert_patch.dart:41:10)
E/flutter ( 3177): #3 JsonDecoder.convert (dart:convert/json.dart:612:36)
E/flutter ( 3177): #4 JsonCodec.decode (dart:convert/json.dart:216:41)
E/flutter ( 3177): #5 jsonDecode (dart:convert/json.dart:155:10)
E/flutter ( 3177): #6 NetworkHelper.ottieniTutteInfo (package:agenda_ferrovia/utilities/networkConnection.dart:36:14)
E/flutter ( 3177): <asynchronous suspension>
E/flutter ( 3177): #7 _ServizioUIAggiungiTrenoState.build.ottieniOrigine (package:agenda_ferrovia/screens/servizioUI/servizioUI_singolo.dart:110:33)
E/flutter ( 3177): <asynchronous suspension>
E/flutter ( 3177): #8 _ServizioUIAggiungiTrenoState.build.<anonymous closure> (package:agenda_ferrovia/screens/servizioUI/servizioUI_singolo.dart:231:23)
E/flutter ( 3177): <asynchronous suspension>
E/flutter ( 3177):
Thanks all for the support! I've found the issue!
Some part of the 'url's String' comes from another call.
Inside a variable there was the "hidden chars" \n. That was the cause of the issue -.-
I've solved removing all chars except letters before save into variable used for the 'url'.
I hope that my English was clear enough to understand.
Bye!

Initialize Dio with persistent cookie at the start of the program

I'm using Dio in my app and I want it to save cookies. It turns out I have to download three additional packages to do that: cookie_jar, dio_cookie_manager and path_provider.
I need to:
get application document directory:
Directory docDir = await getApplicationDocumentsDirectory();
pass it to PersistCookieJar
PersistCookieJar(storage: FileStorage(appDocDir.path + '/.cookies/'));
and add it to interceptors:
dio.interceptors.add(CookieManager(_cookieJar));
My problem is with the first part. For some reason, getApplicationDocumentsDirectory(); throws an error when not used inside a StatefulWidget widget.
I have two questions:
Why on earth would getting a path require a StatefulWidget?
How can I do what I want? I need to initialize Dio as early as possible so that by the time the UI loads, the user is already (or almost) logged in. Plus, I don't want to put the logic of initiating the client object inside the UI code, that might for example cause it to be initiated multiple times whenever the widget is created.
What my code looks like right now:
Future<void> initStuff() async {
initLocator();
Directory docDir = await getApplicationDocumentsDirectory(); // throws
print('docDir = ${docDir.path}');
Client cli = Client(docDir);
locator.registerSingleton<Client>(cli);
// ...
}
void main() async {
await initStuff();
runApp(MyApp());
}
Client constructor:
Client(Directory appDocDir) {
final _cookieJar = PersistCookieJar(storage: FileStorage(appDocDir.path + '/.cookies/'));
dio = Dio()
..options.baseUrl = Utils.SERVER_ADDRESS
..options.sendTimeout = 5000
..options.receiveTimeout = 5000
..options.connectTimeout = 5000
..interceptors.add(CookieManager(_cookieJar));
}
The error I'm getting:
E/flutter (24953): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Null check operator used on a null value
E/flutter (24953): #0 MethodChannel.binaryMessenger
package:flutter/…/services/platform_channel.dart:142
E/flutter (24953): #1 MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:148
E/flutter (24953): #2 MethodChannel.invokeMethod
package:flutter/…/services/platform_channel.dart:331
E/flutter (24953): #3 MethodChannelPathProvider.getApplicationDocumentsPath
package:path_provider_platform_interface/src/method_channel_path_provider.dart:50
E/flutter (24953): #4 getApplicationDocumentsDirectory
package:path_provider/path_provider.dart:138
E/flutter (24953): #5 initStuff
package:proj/main.dart:20
E/flutter (24953): #6 main
package:proj/main.dart:63
E/flutter (24953): #7 _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:142:25)
E/flutter (24953): #8 _rootRun (dart:async/zone.dart:1354:13)
E/flutter (24953): #9 _CustomZone.run (dart:async/zone.dart:1258:19)
E/flutter (24953): #10 _runZoned (dart:async/zone.dart:1789:10)
E/flutter (24953): #11 runZonedGuarded (dart:async/zone.dart:1777:12)
E/flutter (24953): #12 _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:138:5)
E/flutter (24953): #13 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
E/flutter (24953): #14 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
OK: Thank you for updating your post.
The error is: Unhandled Exception: Null check operator used on a null value
It's coming from the 3rd party library call getApplicationDocumentsDirectory(), and it's occurring because you're calling a (currently uninitialized) value with null-safety enabled (a Good Thing!).
SUGGESTIONS:
Using a StatefulWidget is a bit more work - but it makes sense here. It also happens to resolve the problem for you, correct?
You might try making docDir nullable (e.g. String? path). This is exactly what the getApplicationDocument page shows:
https://pub.dev/documentation/path_provider/latest/path_provider/getApplicationDocumentsDirectory.html
Future<Directory> getApplicationDocumentsDirectory() async {
final String? path = await _platform.getApplicationDocumentsPath();
if (path == null) {
throw MissingPlatformDirectoryException(
'Unable to get application documents directory');
}
return Directory(path);
}
Finally, check out these links:
https://stackoverflow.com/a/67990442/421195
https://stackoverflow.com/a/68876902/421195
Run this in main() before everything else:
WidgetsFlutterBinding.ensureInitialized();

The getter 'data' was called on null in response

I expext response.data to be when i got an error 422, like
{
"message": "You can NOT add a penalty!"
}
but i have an error The getter 'data' was called on null.
Future transferCoinsToUser(
String apiToken, String recipientBill, int coin) async {
Response response;
try {
response = await _dio.post(apiEndpoint + "bills/transfer",
options: Options(headers: {"Authorization": apiToken}),
data: {"recipient_bill": recipientBill, "coin": coin});
if(response.statusCode == 200){
print('status cod ' + response.statusCode.toString());
print('response bady ' + response.data.toString());//{message: completed successfully.}
}
} on DioError catch (error) {
print(error);
print(response.data);// The getter 'data' was called on null.
return null;
}
}
my stack trace
NoSuchMethodError: The getter 'data' was called on null.
I/flutter ( 7462): Receiver: null
I/flutter ( 7462): Tried calling: data
I/flutter ( 7462): NoSuchMethodError: The getter 'data' was called on null.
I/flutter ( 7462): Receiver: null
I/flutter ( 7462): Tried calling: data
I/flutter ( 7462): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
I/flutter ( 7462): #1 ApiProvider.transCoinToUser (package:no_fine/data/api_provider.dart:104:22)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #2 TransferRepositoryImpl.transCoinToUser (package:no_fine/data/repository/transfer_repo.dart:37:20)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #3 TransferBloc._mapTransferCoinsToUserToState (package:no_fine/bloc/auth/translations_bloc/translations_bloc.dart:42:33)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #4 TransferBloc.mapEventToState (package:no_fine/bloc/auth/translations_bloc/translations_bloc.dart:26:14)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #5 Bloc._bindEventsToStates.<anonymous closure> (package:bloc/src/bloc.dart:232:20)
I/flutter ( 7462): #6 Stream.asyncExpand.<anonymous closure>.<anonymous closure> (dart:async/stream.dart:644:30)
I/flutter ( 7462): #7 _rootRunUnary (dart:async/zone.dart:1198:47)
I/flutter ( 7462): #8 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
I/flutter ( 7462): #9 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
I/flutter ( 7462): #10 _BufferingStreamSubscription._sendData (dart:a
response might be null. You are calling .data on null hence the error. Try
print(response?.data)
or check
if(response != null) print(response.data);
You can't access the Response object, when you have an error. Instead, Please use below code:
on DioError catch (error) {
print(error);
print(error.response.data);// Here you will find the error response in error object
return null;
}
You can check your request host. In Android device you can not use the request host like "localhost" or "127.0.0.1" directly because this is the Android device's host and this is not your API host.You should use your API host's IP which like "http://192.168.50.123/request?foo=bar".