My debug statement is displaying the database correctly, by after something is going wrong and in getting the error: Unhandled Exception: NoSuchMethodError: Class 'int' has no instance method '[]'. I am getting null data when I'm trying to display is in my application, this is because the list i am using to store the values has length 0
following is my class
class UserDetails extends ChangeNotifier {
final String? userId;
final String? mobileno;
bool? userStatus;
final String? adhar;
final String? pan;
final String? adharno;
final String? panno;
UserDetails(
{this.userId,
this.mobileno,
this.userStatus = false,
this.adhar,
this.pan,
this.adharno,
this.panno});
}
following is my api where I am facing error
Future<void> getUsers(BuildContext context) async {
final url = '${PurohitApi().baseUrl}${PurohitApi().users}';
final List<UserDetails> loadedUsers = [];
try {
final client = RetryClient(
http.Client(),
retries: 4,
when: (response) {
return response.statusCode == 401 ? true : false;
},
onRetry: (req, res, retryCount) async {
//print('retry started $token');
if (retryCount == 0 && res?.statusCode == 401) {
var accessToken = await Provider.of<Auth>(context, listen: false)
.restoreAccessToken();
// Only this block can run (once) until done
req.headers['Authorization'] = accessToken;
}
},
);
var response = await client.get(
Uri.parse(url),
headers: {'Authorization': authToken!},
);
final extractedData = json.decode(response.body) as Map<String, dynamic>;
print(extractedData);
if (extractedData['data'] == null) {
return;
}
extractedData.forEach((userId, userData) {
print(userId);
loadedUsers.add(
UserDetails(
userId: userData['data']['id'],
mobileno: userData['data']['mobileno'],
userStatus: userData['data']['userstatus'],
adhar: userData['data']['adhar'],
pan: userData['data']['pan'],
adharno: userData['data']['adharno'],
panno: userData['data']['panno'],
),
);
});
_users = loadedUsers.reversed.toList();
//print(users);
notifyListeners();
} catch (e) {
print(e);
}
}
}
I am facing NoSuchMethodError: Class 'int' has no instance method '[]'Tried calling: from above api following is my response
I think userId should not be String, It should be an integer
class UserDetails extends ChangeNotifier {
final int? userId;
final String? mobileno;
bool? userStatus;
final String? adhar;
final String? pan;
final String? adharno;
final String? panno;
UserDetails(
{this.userId,
this.mobileno,
this.userStatus = false,
this.adhar,
this.pan,
this.adharno,
this.panno});
}
try to print your data in this error I think your data should be like userData['id'],
the above error is you try to use int as an object in the data returned
the returned userData is an int
change this code :
extractedData.forEach((userId, userData) {
print(userId);
loadedUsers.add(
UserDetails(
userId: userData['data']['id'],
mobileno: userData['data']['mobileno'],
userStatus: userData['data']['userstatus'],
adhar: userData['data']['adhar'],
pan: userData['data']['pan'],
adharno: userData['data']['adharno'],
panno: userData['data']['panno'],
),
);
});
to this :
loadedUsers.add(
UserDetails(
userId: extractedData['data']['id'],
mobileno: extractedData['data']['mobileno'],
userStatus: extractedData['data']['userstatus'],
adhar: extractedData['data']['adhar'],
pan: extractedData['data']['pan'],
adharno: extractedData['data']['adharno'],
panno: extractedData['data']['panno'],
),
);
the reason why :
extractedData is a map<String,dynamic>, when you call function forEach(key, value) :
the value is not a map, is an Object, or dynamic. the key is a String.
when you call this fuction :
value['data]
its will throw that error
if you extractedData is a List of Map, you can keep you original code, and change type of extractedData to List :
final extractedData = json.decode(response.body) as List<Map<String, dynamic>>;
Edit :
your data in the response is a list Of a map so the code will be this :
final extractedData = json.decode(response.body) as Map<String,dynamic>;
List<Map<String,dynamic>> data = extractedData['data'];
for (var map in data){
loadedUsers.add(
UserDetails(
userId: map['id'],
mobileno: map['mobileno'],
userStatus: map['userstatus'],
adhar: map['adhar'],
pan: map['pan'],
adharno: map['adharno'],
panno: map['panno'],
),
);
}
Related
Im trying to make a searchbar that fetch data from mysql , but i have a problem that when i call data fetch function it returns
Instance of '_Future<List>'
this is my code
Future<List<Students>> getStudents(String id) async {
var url = 'http://localhost/getStudents.php';
final response = await http.post(Uri.parse(url), body: {
'id':id,
});
var res = jsonDecode(response.body)['fname'] as List;
if (response.statusCode == 200) {
return res.map((std) => Students.fromJson(std)).toList();
}else {
throw Exception('Failed to load shows');
}
}
my class :
class Students{
final int id;
final String fname;
final String sname;
final String tname;
const Students( {
required this.id,
required this.sname,
required this.tname,
required this.fname,
});
factory Students.fromJson(Map<String, dynamic> json) => Students(
id: json['Id'],
sname: json['secname'],
tname:json['thirdname'] ,
fname: json['firstname'],
);
}
getStudents is a future function and you need to await for it:
List<Students> result = await getStudents('');
Hello everyone!
I am trying to fetch my product Data from Firebase server ,when i sign in i got this error:
Unhandled Exception: NoSuchMethodError: The method '[]' was called on null.
when I face this problem before i added these variable to the function below:
bool? _isFavorite =
favoriteData[key] != null || favoriteData[key] == 'true'
? true
: false;
but when i deleted favorite data from the server it gave me error again! it should take the "False"value when it null!
i think my error related to null safety but i cant fix it
i will share the Function which related to to this error and model and if there any solution I would be grateful for it ,Thank you!
Fetch Data Function:
Future<void> fetchAndSetProducts([bool filterByUser = false]) async {
final filterString =
filterByUser ? 'orderBy="creatorId"&equalTo="$userId"' : '';
var url =
'https://ecommerce-test-753ad-default-rtdb.firebaseio.com/products.json?auth=$authToken&$filterString';
try {
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body) as Map<String, dynamic>;
if (extractedData == {}) {
return;
}
url =
'https://ecommerce-test-753ad-default-rtdb.firebaseio.com/userFavorites/$userId.json?auth=$authToken';
final favoriteResponse = await http.get(Uri.parse(url));
final favoriteData = json.decode(favoriteResponse.body);
print(favoriteData);
print(extractedData);
final List<Product> loadedProduct = [];
extractedData.forEach((key, value) {
bool? _isFavorite =
favoriteData[key] != null || favoriteData[key] == 'true'
? true
: false;
loadedProduct.add(
Product(
id: key,
title: value['title'],
price: value['price'],
imageUrl: value['imageUrl'],
description: value['description'],
isFavorite: _isFavorite,
),
);
});
_productItems = loadedProduct;
notifyListeners();
} catch (e) {
rethrow;
}
}
product Model class:
class Product with ChangeNotifier {
final String id;
final String title;
final double price;
final String imageUrl;
final String description;
bool isFavorite;
Product({
required this.id,
required this.title,
required this.price,
required this.imageUrl,
required this.description,
this.isFavorite = false,
});
void _setFavValue(bool newValue) {
isFavorite = newValue;
notifyListeners();
}
Future<void> toggleFavoriteStatus(String authToken, String
userId) async {
final oldStatus = isFavorite;
isFavorite = !isFavorite;
notifyListeners();
final url =
'https://ecommerce-test-753ad-default-
rtdb.firebaseio.com/userFavorites/$userId/$id.json?
auth=$authToken';
try {
final response = await http.put(
Uri.parse(url),
body: json.encode(isFavorite),
);
if (response.statusCode >= 400) {
_setFavValue(oldStatus);
}
} catch (error) {
_setFavValue(oldStatus);
}
}
I also Added this line to Firebase rules:
"products":{
".indexOn":["creatorId"],
By checking favoriteData[key] for null is not enough, it is possible that favoriteData itself is null, try this:
bool? _isFavorite =
favoriteData != null && favoriteData[key] != null && favoriteData[key] == 'true'
? true
: false;
Try this:
final value = favoriteData == null ? false : favoriteData[key] != null || favoriteData[key] == 'true';
bool? _isFavorite = value;
im new in flutter , and i want to display my data from api json to my app with ResteApi ,
i made a model like that :
class Todo {
final int id;
final String title;
final bool completed;
Todo({required this.id, required this.title, required this.completed});
factory Todo.fromJson(Map<String, dynamic> json) {
return Todo(
id: json["id"] as int,
title: json["title"] as String,
completed: json["completed"] as bool);
}
Map<String, dynamic> toJson() => {'title': title, 'completed': completed};
#override
String toString() {
return 'Todo{id: $id, title: $title, completed: $completed}';
}
}
And a methode get in service class Like that :
final String apiUrl = "https://jsonplaceholder.typicode.com/todos";
Future<List<Todo>> getCases() async {
Response res = await get(Uri.parse(apiUrl));
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Todo> todo = body.map((dynamic item) => todo.fromJson(item)).toList();
return todo;
} else {
throw "Failed to load cases list";
}
}
but this errors it display to me:
A value of type 'List<dynamic>' can't be assigned to a variable of type 'List<Todo>'.
Try changing the type of the variable, or casting the right-hand type to 'List<Todo>'
how can i fix it
There is a typo todo.fromJson, it will be Todo.fromJson
List<Todo> todo = body.map((dynamic item) => Todo.fromJson(item)).toList();
Also it is better to accept null data
List<dynamic>? body = jsonDecode(res.body);
final todo =
body?.map((dynamic item) => Todo.fromJson(item)).toList() ?? [];
return todo;
Try this:
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Todo> todo = body.map<Todo>((item) => Todo.fromJson(item)).toList();
return todo;
} else {
throw "Failed to load cases list";
}
// create function like this inside ApiFunctionsCall() class
Future<String?> dataListApiCalls() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
final response = await http.get(Uri.parse('url_of_api'));
if (response.statusCode == 200) {
//print(response.body);
return response.body;
}
} else {
print("check internet connection");
}
} catch (e) {
print(e);
}
}
//then in call function other file
// create list
List<Todo> searchDataList = [];
// other function
void getDataList() async {
final response = await ApiFunctionsCall().dataListApiCalls();
final searchModalDataClass = jsonDecode(response!);
setState(() {
for (var i = 0; i < searchModalDataClass.data.length; i++) {
Todo todo = Todo(
id: searchModalDataClass.data[i].id,
email: searchModalDataClass.data[i].email,
searchDataList.add(todo);
}
});
}
I am trying to conver JSON file to List so I can use it with DropdownMenuItem. The method stops whenever I am trying to decode the response and throws this error: Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<Country>' How can I solve this??
method:
List<Country> _countryList = [];
Future<void> readJson() async {
final String response = await rootBundle.loadString('assets/countries.json');
print(response);
final List<Country> data = await json.decode(response).map((e) => Country.fromJson(e)).toList();
setState(() {
_countryList = data;
});
}
My Json looks like this
[
{
"value": "AFG",
"label": "Afghanistan",
"eu": false
},
....
]
Country model class
class Country {
String value;
String label;
bool eu;
Country({
required this.value,
required this.label,
required this.eu,
});
factory Country.fromJson(Map<String, dynamic> json) {
return Country(
value: json["value"],
label: json["label"],
eu: json["eu"],
);
}
}
json.decode(..) returns dynamic type and in your case you need to cast it to List
final decodedJson = jsonDecode(response) as List;
now take the decodedJson and cast its generic type
final castedList = decodedJson.cast<Map<String, dynamic>>();
now it will be so simple to map it to dart object Country
final List<Country> data = castedList.map((e) => Country.fromJson(e)).toList();
the final result:
List<Country> _countryList = [];
Future<void> readJson() async {
final String response = await rootBundle.loadString('assets/countries.json');
print(response);
final decodedJson = jsonDecode(response) as List;
final castedList = decodedJson.cast<Map<String, dynamic>>();
final List<Country> data =
castedList.map((e) => Country.fromJson(e)).toList();
setState(() {
_countryList = data;
});
}
I have a class which will fetch the imgUrl on first creation in the constructor.
And I need to write a test to make sure that the get method of Dio instance is called.
However, I have trouble that the fetch result returns null instead of Future so that I cannot call then.
The class:
#JsonSerializable()
class DogBreed with ChangeNotifier {
#JsonKey(ignore: true)
final Dio dio;
final String id;
final String bred_for;
final String breed_group;
final String life_span;
final String name;
final String origin;
final String temperament;
final String description;
final Measurement height;
final Measurement weight;
var imgUrl = '';
DogBreed({
this.dio,
this.id,
this.bred_for,
this.breed_group,
this.life_span,
this.name,
this.origin,
this.temperament,
this.description,
this.height,
this.weight,
}) {
dio.get(
'xxxxx,
queryParameters: {
'breed_id': id,
'limit': 1,
},
).then((result) {
final List data = result.data;
if (result.statusCode == 200) {
if (data.isNotEmpty) {
imgUrl = result.data[0]['url'];
} else {
imgUrl = NO_IMAGE_AVAILABLE_URL;
}
notifyListeners();
}
});
}
factory DogBreed.fromJson(Map<String, dynamic> json) =>
_$DogBreedFromJson(json);
}
My test:
class MockDio extends Mock implements Dio {}
void main() {
MockDio mockDio;
setUp(() {
mockDio = MockDio();
});
test(
"fetch the imageUrl on constructor",
() async {
when(mockDio.get(any))
.thenAnswer((_) async => Response(data: 'url', statusCode: 200));
final newBreedProvider = DogBreed(
dio: mockDio,
id: '12',
);
verify(mockDio.get(
'xxxx',
queryParameters: {
'breed_id': 12,
'limit': 1,
},
));
},
);
}
Result when run test:
dart:core Object.noSuchMethod
package:practises/projects/dog_facts/providers/dog_breed.dart 46:7 new DogBreed
test/projects/dog_facts/providers/dog_breed_test.dart 24:32 main.<fn>
NoSuchMethodError: The method 'then' was called on null.
Receiver: null
Tried calling: then<Null>(Closure: (Response<dynamic>) => Null)
Could anyone help me to figure out how to write this test or suggest me a new way of implementing so that I can write a test on this one?
I figured out why, it's my mistake that I need to provide queryParameters for get method in the test. It should be:
when(
mockPdio.get(
any,
queryParameters: anyNamed('queryParameters'),
),
).thenAnswer((_) async => Response(data: 'url', statusCode: 200));
Cheers.