Invalid argument(s): Illegal argument in isolate message : (object is a closure - Function 'createDataList':.) - flutter

I tried to fetch data from the internet with moviedb API, I followed the tutorial at https://flutter.io/cookbook/networking/fetch-data/
but I'm getting the below error.
Invalid argument(s): Illegal argument in isolate message : (object is a closure - Function 'createDataList':.)
This my code
Future<List<DataModel>> fetchData() async{
final response = await http.get("https://api.themoviedb.org/3/movie/now_playing?api_key=d81172160acd9daaf6e477f2b306e423&language=en-US");
if(response.statusCode == 200){
return compute(createDataList,response.body.toString());
}
}
List<DataModel> createDataList(String responFroJson) {
final parse = json.decode(responFroJson).cast<Map<String, dynamic>>();
return parse.map<DataModel> ((json) => DataModel.fromtJson(json)).toList();
}
Screenshot of the error message

compute can only take a top-level function, but not instance or static methods.
Top-level functions are functions declared not inside a class
and not inside another function
List<DataModel> createDataList(String responFroJson) {
...
}
class SomeClass { ... }
should fix it.
https://docs.flutter.io/flutter/foundation/compute.html
R is the type of the value returned. The callback argument must be a top-level function, not a closure or an instance or static method of a class.

As per today (2020. Aug) the compute is working fine with static methods.
For me, the issue was that I was trying to return a http.Response object from the compute() methods.
What I did is I've created a simplified version of this class, containing what I need:
class SimpleHttpResponse {
String body;
int statusCode;
Map<String, String> headers;
}
Then I've updated the original method from this:
static Future<http.Response> _executePostRequest(EsBridge bridge) async {
return await http.post(Settings.bridgeUrl, body: bridge.toEncryptedMessage());
}
to this:
static Future<SimpleHttpResponse> _executePostRequest(EsBridge bridge) async {
http.Response result = await http.post(Settings.bridgeUrl, body: bridge.toEncryptedMessage());
if (result == null) {
return null;
}
SimpleHttpResponse shr = new SimpleHttpResponse();
shr.body = result.body;
shr.headers = result.headers;
shr.statusCode = result.statusCode;
return shr;
}
Worked like charm after this change. Hope this helps somebody ranning into similar problem.

Related

Flutter - loop not working while parsing json

I am trying to create model and parse json data from api
for that i created the model class you can see below
class FeatureModel {
String? PlanFeatures;
bool? FeatureStatus;
FeatureModel({this.PlanFeatures, this.FeatureStatus});
FeatureModel.fromJson(parsonJson) {
PlanFeatures = parsonJson['PlanFeatures'];
FeatureStatus = parsonJson['FeatureStatus'];
}
}
now i am trying to parse json with the help of loop
let me show you my method
List<FeatureModel> featureModel = [];
Uri featureAPI = Uri.parse(
planFeatureApi);
apiCall() async {
try {
http.Response response = await http.get(featureAPI);
// print(response.statusCode);
if (response.statusCode == 200) {
var decode = json.decode(response.body);
print(decode);
for (var i = 0; i < decode.length; i++) {
print(i);
featureModel.add(
FeatureModel.fromJson(decode[i]),
);
}
}
} catch (e) {}
}
I am calling it here
onPressed: () async{
await apiCall();
}
but the problem is here
loop is not working while parsing data
in that particular code i remains on 0 only
when i removes featureModel.add( FeatureModel.fromJson(decode[i]), ); i started increaing till 10
please let me know if i am making any mistake or what
thanks in advance
Here is the sample of api respone
[{"PlanFeatures":"Video Link Sharing","FeatureStatus":"true"},{"PlanFeatures":"Email \u0026amp; Telephonic Support","FeatureStatus":"true"},{"PlanFeatures":"Remove Pixeshare Branding","FeatureStatus":"false"},{"PlanFeatures":"Add Custom logo on uploaded photos","FeatureStatus":"false"},{"PlanFeatures":"Get Visitor Info","FeatureStatus":"false"},{"PlanFeatures":"Mobile Apps","FeatureStatus":"false"},{"PlanFeatures":"Send Questionnaries","FeatureStatus":"false"},{"PlanFeatures":"Create \u0026amp; Send Quotation","FeatureStatus":"false"},{"PlanFeatures":"Online Digital Album Sharing","FeatureStatus":"false"},{"PlanFeatures":"Analytics","FeatureStatus":"false"}]
thanks
I found many errors, first, the fromJson is not a factory constructor and doesn't return a class instance from the JSON.
the second one is that the bool values from the sample you added are String not a bool so we need to check over it.
try changing your model class to this:
class FeatureModel {
String? PlanFeatures;
bool? FeatureStatus;
FeatureModel({this.PlanFeatures, this.FeatureStatus});
factory FeatureModel.fromJson(parsonJson) {
return FeatureModel(
PlanFeatures: parsonJson['PlanFeatures'],
FeatureStatus: parsonJson['FeatureStatus'] == "false" ? false : true,
);
}
}

Create a class that calls a future for reusability

I have a future that is used a few different times on some pages and I'm trying to include it instead and reference it when needed to cut down on the code overhead.
I've created a working future and wrapped it inside a class, the problem is that Flutter states that
"2 positional argument(s) expected, but 0 found."
I've tried String and Function type declarations for the client variable and I am including them, but I'm not sure what else I'm missing here?
FetchCats.getCats(client: http.Client(), filter: filter);
class FetchCats {
String client; <-- this shouldn't be string but I don't know what else to declare it as
int catType;
FetchCats({Key? key, required this.client, required this.catType});
Future<List<CatDetails>> getCats(http.Client client, int catType) async {
var ct = catType;
var catResults;
var response = await client.get(Uri.parse('/cats/breeds/$ct/'));
if (response.statusCode == 200) {
catResults = compute(convertCatDetails, response.body);
} else {
print("error");
}
return catResults;
}
}
List<CatDetails> convertCatDetails(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed
.map<CatDetails>((json) => CatDetails.fromJson(json))
.toList();
}
Your function is defined using positional parameters, rather than named parameters, but you are calling it with named arguments.
Here are a few changes that should allow you to use the class as I think you're intending:
It's not necessary to store catType on the class, since that's something you would probably change between requests - so it makes more sense to only pass it into the getCats function.
To fix the positional parameter issue, you can also change catType into a named parameter.
You don't need a Key parameter on the constructor - those are usually used with Widgets.
The type of the client should be http.Client, not String.
With those changes, your class should look something like this:
class FetchCats {
final http.Client client;
FetchCats({required this.client});
Future<List<CatDetails>> getCats({required int catType}) async {
int ct = catType;
var catResults;
var response = await client.get(Uri.parse('/cats/breeds/$ct/'));
if (response.statusCode == 200) {
catResults = compute(convertCatDetails, response.body);
} else {
print("error");
// Return an empty list, rather than the uninitialized catResults
return [];
}
return catResults;
}
}

(ERROR) A value of type 'Adhan' can't be returned from the method 'getAdhan' because it has a return type of 'Future<List<Adhan>?>'

this code is for fetching data from json api , there is just one error in the code , and this is the error :
error
class RemoteService {
Future<List<Adhan>?> getAdhan() async {
var client = http.Client();
var uri = Uri.parse("https://api.pray.zone/v2/times/today.json?city=paris");
var response = await client.get(uri);
if (response.statusCode == 200) {
var json = response.body;
return adhanFromJson(json);
}
}
}
I tried to search in the Internet and YouTube for any problem similar to my problem, I did not find anything to help me.
how can i fix this error ?
Your function named adhanFromJson probably returns a Adhan, while getAdhan expects you to return a List<Adhan> or null.
Either change the return type of getAdhan or return a List<Adhan>.

The input does not contain any JSON tokens (Blazor, HttpClient)

i have an http Get method like below
public async Task<Ricetta> GetRicettaByNome(string nome)
{
Ricetta exist = default(Ricetta);
var ExistRicetta = await appDbContext.Ricetta.FirstOrDefaultAsync(n => n.Nome == nome);
if(ExistRicetta != null)
{
exist = ExistRicetta;
return exist;
}
exist = null;
return exist;
}
It gets called by a controller like this:
[HttpGet("exist/{nome}")]
public async Task<ActionResult<Ricetta>> GetRicettaByNome(string nome)
{
try
{
if (string.IsNullOrEmpty(nome))
{
return BadRequest();
}
var result = await ricetteRepository.GetRicettaByNome(nome);
if (result != null)
return result;
return default(Ricetta);
}
catch (Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, "NON HAI INTERNET!");
}
}
But when i call my api to get the resposne by an httpclient like this:
public async Task<Ricetta> GetRicettaByNome(string nome)
{
return await httpClient.GetJsonAsync<Ricetta>($"api/Ricette/exist/{nome}");
}
i got this error:
the input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.'
This is the expected result when you return null from your API. And default(Ricetta) is the same as null.
You will have to handle this some other way. GetJsonAsync<T>() is convenient shorthand when you know you will always have data. It is not the best option for dealing with null.
You can see (in dev tools) that the status code is 204 (No Content) for null. You can detect that or catch the error from GetJsonAsync.
Your error exist in your repository part where GetJsonAsync<>. You need to use HttpResponseMessage and check the content before Deserialize for example:
private async ValueTask<T> GetJsonAsync(string ur)
{
using HttpResponseMessage response = awiat _client.GetAsync(url);
//some method to validate response
ValidateResponse(response);
//then validate your content
var content = await ValidateContent(response).ReadAsStringAsync();
return JsonSerializer.Desrialize<T>(content, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
}
//Here is the method that you need
private HttpContent ValidateContent(HttpResponseMessage response)
{
if(string.IsNullOrEmpty(response.Content?.ReadingAsString().Result))
{
return response.Content= new StringContent("null",Encoding.UTF8, MediaTypeNames.Application.Json);
}
else
{
return response.Content;
}
}

error: Only static members can be accessed in initializers

i will import images BASE64 stored in DB.
code :
profileimage()async{
var userimage1 = await DBHelper().getuserIMAGE1('roro');
print(userimage1);
if(userimage1 == Null){
print('Empty');
}else{
setState(() {
userimage1.map((e) {
tmpimage = e['image0'];
}).toList();
print(tmpimage);
_TmpBytesImage = Base64Decoder().convert(tmpimage);
print(_TmpBytesImage);
return Image.memory(_TmpBytesImage);
});
}
}
File pimage = profileimage(); << error
and i got error 'flutter: Only static members can be accessed in initializers'
how can i do?
You need to call like below.
Future.delayed(Duration.zero, () {
// your code
});
The following items appear wrong:
Your return statement is inside a setstate() function so returns a value from that function.
processImage probably should be
Static Future processImage()
The call should be something like below but not at class level. It also needs to of type Image not of type File.
pimage = await processImage();
If there is nothing in the database, what do you want to return?