Flutter HTTP issues - flutter

With the new update, some HTTP functionality has changed. This function used to work and now it does not. Can someone explain what changed?
import 'package:http/http.dart';
void getData() async {
Response response = await get('https://jsonplaceholder.typicode.com/todos/1');
Map data = JsonDecode(responce.body);
print(data);
}
lib/pages/loading.dart:24:37: Error: The argument type 'String' can't be assigned to the parameter type 'Uri'.
- 'Uri' is from 'dart:core'.
Response response = await get('https://jsonplaceholder.typicode.com/todos/1');

You can try this:
import 'package:http/http.dart' as http;
void getData() async {
var response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/todos/1'));
var data = jsonDecode(response.body) as Map;
print(data);
}
UPDATE: Inserting code for WorldTimeApi
NetService:
class NetService {
static Future<T?> getJson<T>(String url, {int okCode = 200}) {
return http.get(Uri.parse(url))
.then((response) {
if (response.statusCode == okCode) {
return jsonDecode(response.body) as T;
}
PrintService.showDataNotOK(response);
return null;
})
.catchError((err) => PrintService.showError(err));
}
}
Main:
import 'dart:async';
import 'package:_samples2/networking.dart';
class WorldTimeApi {
static const _url = 'http://worldtimeapi.org/api/timezone';
static FutureOr<void> fetchTime(String relPath) async {
await NetService.getJson(_url + relPath)
.then((response) => print(response))
.whenComplete(() => print('\nFetching done!'));
}
}
void main(List<String> args) async {
await WorldTimeApi.fetchTime('/America/Los_Angeles');
print('Done!');
}
Result:
{abbreviation: PST, client_ip: 179.6.56.125, datetime: 2021-03-09T17:24:09.367903-08:00, day_of_week: 2, day_of_year: 68, dst: false, dst_from: null, dst_offset: 0, dst_until: null, raw_offset: -28800, timezone: America/Los_Angeles, unixtime: 1615339449, utc_datetime: 2021-03-10T01:24:09.367903+00:00, utc_offset: -08:00, week_number: 10}
Fetching done!
Done!

Related

Get request of google maps api from postman is working properly but in the app it is showing null(NoSuchMethodError)

Why is the GET request to the Google Maps API working properly in Postman but showing a null error (NoSuchMethodError) when implemented in the app?
Environment
I've configured a local REST API:
static const String BASE_URL = "http://localhost:8000";
static const String GEOCODE_URI = "api/v1/config/geocode-api";
Code I'm Using
Here are the excerpts of the code I'm attempting this with.
The main implementation is in location_controller.dart:
<!-- location_controller.dart -->
import 'package:ecommerceapp/models/address_model.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get_connect/http/src/response/response.dart';
import 'package:get/get_state_manager/get_state_manager.dart';
import 'package:ecommerceapp/data/repositary/location_repo.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class LocationController extends GetxController implements GetxService {
LocationRepo locationRepo;
LocationController({
required this.locationRepo,
});
bool _loading = false;
late Position _position;
late Position _pickPosition;
Placemark _placemark = Placemark();
Placemark _pickPlacemark = Placemark();
List<AddressModel> _addressList = [];
late List<AddressModel> _allAddressList = [];
List<String> _addressTypelist = ["home", "office", "others"];
int _addressTypeIndex = 0;
late Map<String, dynamic> _getAddress;
late GoogleMapController _mapController;
List<AddressModel> get addressList => _addressList;
bool get loading => _loading;
Position get position => _position;
Position get pickPosition => _pickPosition;
Map get getAddress => _getAddress;
bool _updateAddressData = true;
bool _changeAddress = true;
void setMapController(GoogleMapController mapController) {
_mapController = mapController;
}
void updatePosition(CameraPosition position, bool fromAddress) async {
print("Update Position");
if (_updateAddressData) {
_loading = true;
update();
try {
if (fromAddress) {
_position = Position(
latitude: position.target.latitude,
longitude: position.target.longitude,
timestamp: DateTime.now(),
heading: 1,
accuracy: 1,
altitude: 1,
speedAccuracy: 1,
speed: 1,
);
} else {
_pickPosition = Position(
latitude: position.target.latitude,
longitude: position.target.longitude,
timestamp: DateTime.now(),
heading: 1,
accuracy: 1,
altitude: 1,
speedAccuracy: 1,
speed: 1,
);
}
if (_changeAddress) {
String _address = await getAddressfromGeocode(LatLng(position.target.latitude, position.target.longitude));
}
} catch (e) {
print(e);
}
}
}
Future<String> getAddressfromGeocode(LatLng latLng) async {
String _address = "Unknown Location Found";
print("Address : $_address");
Response response = await locationRepo.getAddressfromGeocode(latLng);
print("Status Code : ${response.statusCode}");
print(response.body);
if (response.body["status"] == "OK") {
_address = response.body["result"][0]['formatted_address'].toString();
print("Printing Address : $_address");
} else {
print("Error getting the google api");
}
return _address;
}
}
which calls the location_repo.dart:
import 'package:ecommerceapp/utils/app_constants.dart';
import 'package:get/get_connect/http/src/response/response.dart';
import 'package:google_maps_flutter_platform_interface/src/types/location.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:ecommerceapp/data/api/api_client.dart';
class LocationRepo {
final ApiClient apiClient;
final SharedPreferences sharedPreferences;
LocationRepo({
required this.apiClient,
required this.sharedPreferences,
});
Future<Response> getAddressfromGeocode(LatLng latLng) async {
return await apiClient.getData('${AppConstants.GEOCODE_URI}'
'?lat=${latLng.latitude}&lng=${latLng.longitude}');
}
}
In the getAddressfromGeocode method, when I tried to print the latitude and longitude, the print statements were also working fine:
Future<Response> getData(String uri, {Map<String, String>? headers}) async {
try {
Response response = await get(
uri,
headers: headers == null ? _mainHeaders : headers,
);
return response;
} catch (e) {
return Response(statusCode: 1, statusText: e.toString());
}
}
But, my code fails and response.body is null:
flutter: NoSuchMethodError: The method '\[\]' was called on null.
Receiver: null
Tried calling: \[\]("status")
I have no idea what I'm doing and still haven't asked ChatGTP, so I did not find any working solutions. Please help.

No stub was found which matches the arguments of this method call

I'm writing a Unit test for my data source and face the problem No stub was found which matches the arguments of this method call
import 'dart:convert';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:true_food/core/constant.dart';
import 'package:true_food/core/network_manager.dart';
import 'package:true_food/features/home/data/datasources/home_data_source.dart';
import 'package:true_food/features/home/data/models/shelve.dart';
import 'package:true_food/features/home/data/models/shelve_banner_list.dart';
import 'package:true_food/features/home/domain/entities/banner_list_request_model.dart';
import '../../../../core/utils/fixture_reader.dart';
import 'home_data_source_test.mocks.dart';
#GenerateMocks([NetworkManager])
main() {
late HomeDataSourceImpl dataSource;
late MockNetworkManager mockNetworkManager;
final successCode = 201;
final shelveUrl = Constant.baseUrl + APIRoute.shelveList;
final bannerUrl = Constant.baseUrl + APIRoute.bannerList;
setUp(() {
mockNetworkManager = MockNetworkManager();
dataSource = HomeDataSourceImpl(mockNetworkManager);
});
void onCallSuccess(Function body) {
group('Get list successfully', () {
body();
});
}
void onCallFailed(Function body) {
group('Get list unsuccessfully', () {
body();
});
}
BannerListRequestModel request = const BannerListRequestModel(
url:
"/weshop/api/TRUEID_TRUEFOOD/shelfContent?type=item&sort=sequence&itemGroup=6183b134b6d93f000180bf76&page={sys.page}&size={sys.size}&publishStatus=true",
location: BannerListRequestLocationModel(latitude: 0.0, longitude: 0.0),
page: 0,
size: 4);
Future<void> makeResponseSuccessfull(dynamic data) async {
final Response response =
Response(requestOptions: RequestOptions(path: 'path'), statusCode: 200);
when(mockNetworkManager.request(
path: shelveUrl,
method: Method.get,
param: {
"publishOnApp": true,
},
headers: null,
isFormData: false,
contentType: 'application/json',
isFullPath: false,
language: "th",
date: null,
file: null,
check: false,
)).thenAnswer((_) async => Right(response));
}
void makeBannerListResponseSuccessfull(dynamic data) async {
final Response response = Response(
requestOptions: RequestOptions(path: 'path'),
statusCode: 200,
data: data);
when(mockNetworkManager.request(
path: bannerUrl,
method: Method.post,
param: request.toMap(),
headers: null,
isFormData: false,
contentType: 'application/json',
isFullPath: false,
language: "th",
date: null,
file: null,
check: false,
)).thenAnswer((_) async => Right(response));
}
onCallSuccess(() {
test('should perform GET for get shelve list successfully', () async {
final json = jsonDecode(fixture("shelve_list_data.json"));
final List<ShelveModel> list =
List<ShelveModel>.from(json.map((e) => ShelveModel.fromJson(e)));
// arrange
await makeResponseSuccessfull(json);
// act
final rs = await dataSource.getList(publishOnApp: true);
// assert
expect(rs, list);
});
test('should perform POST for get banner list successfully', () async {
final json = jsonDecode(fixture("banner_list_data.json"));
final List<ShelveBannerListModel> list = List<ShelveBannerListModel>.from(
json.map((e) => ShelveBannerListModel.fromJson(e)));
// arrange
makeBannerListResponseSuccessfull(json);
// act
final rs = await dataSource.getBannerList(request: request);
// assert
expect(rs, list);
});
});
}
My NetworkManager class:
import 'dart:convert';
import 'dart:io';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:flutter_flavor/flutter_flavor.dart';
import 'package:injectable/injectable.dart';
import 'package:true_food/core/constant.dart';
import 'package:true_food/core/error/error.dart';
import 'package:true_food/core/error/exceptions.dart';
import 'package:true_food/core/local_storage.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:true_food/gen/locale_keys.g.dart';
import 'package:dio/adapter.dart';
#lazySingleton
class NetworkManager {
final dio = Dio();
Future<Either<ServerException, Response>> request({
required String path,
required Method method,
Map<String, dynamic>? param,
Map<String, dynamic>? headers,
bool isFormData = false,
String contentType = 'application/json',
bool isFullPath = false,
String language = 'vi',
// ignore: avoid_init_to_null
DateTime? date = null,
// ignore: avoid_init_to_null
FormData? file = null,
bool check = false,
}) async {
final String? _token = LocalStorage().getString(Constant.accessToken);
print('_token: $_token');
String domain = FlavorConfig.instance.variables["baseUrl"] ?? '';
String _finalPath = domain + path;
Map<String, dynamic> _finalParam = {};
if (param != null) {
print(param);
_finalParam.addAll(param);
}
try {
Map<String, dynamic>? _header =
_token != null ? {"Authorization": "Bearer " + _token} : null;
Response response = Response(requestOptions: RequestOptions(path: path));
Options optionsCommon = Options(
headers: _header,
sendTimeout: 30 * 1000,
receiveTimeout: 30 * 1000,
contentType: contentType,
);
//handle old printic with the request without content type
switch (method) {
case Method.get:
response = await dio.get(
_finalPath,
queryParameters: _finalParam,
options: optionsCommon,
cancelToken: null,
onReceiveProgress: null,
);
break;
case Method.post:
var data = isFormData ? file : _finalParam;
response = await dio.post(
_finalPath,
options: optionsCommon,
data: data,
cancelToken: null,
onReceiveProgress: null,
);
break;
case Method.put:
var data = isFormData ? file : _finalParam;
response = await dio.put(
_finalPath,
options: optionsCommon,
data: data,
cancelToken: null,
onReceiveProgress: null,
);
break;
case Method.delete:
var data = isFormData ? file : _finalParam;
response = await dio.delete(
_finalPath,
options: optionsCommon,
data: data,
cancelToken: null,
);
break;
}
print('==> DIO SUCCESS <$path> RESPONSE :\n'
'${response.data}');
// onSuccess(response.data, response.statusCode ?? 200);
return Right(response);
} on DioError catch (e) {
if (e.response != null) {
final Response rp = e.response!;
if (rp.statusCode == 502) {
// showToast("Server is maintaining, please login later".tr());
// UserManager.instance.logout();
// EasyLoading.dismiss();
}
print('~~> e: ${e.error}');
print('==> DIO FAILED <$path> RESPONSE :\n'
'${e.response?.data ?? ""}');
final data = rp.data;
try {
final json = jsonDecode(data);
return Left(ServerException(appError: AppError.fromJson(json)));
} on Exception {
return Left(ServerException(
appError: AppError(
status: 500,
title: LocaleKeys.something_went_wrong.tr(),
message: LocaleKeys.something_went_wrong.tr())));
}
} else {
return Left(ServerException(
appError: AppError(
status: 500,
title: LocaleKeys.something_went_wrong.tr(),
message: LocaleKeys.something_went_wrong.tr(),
),
));
}
} on SocketException {
return Left(ServerException(
appError: AppError(
status: 500,
title: LocaleKeys.something_went_wrong.tr(),
message: LocaleKeys.something_went_wrong.tr())));
}
}
}
enum Method { post, get, put, delete }
Pubspec:
Mockito version: "5.1.0"
Dio version "4.0.5"
MissingStubError: 'request'
No stub was found which matches the arguments of this method call:
request({path: api/shelves, method: Method.get, param: {publishOnApp: true}, headers: null, isFormData: false, contentType: application/json, isFullPath: false, language: vi, date: null, file: null, check: false})
Add a stub for this method using Mockito's 'when' API, or generate the MockNetworkManager mock with a MockSpec with 'returnNullOnMissingStub: true' (see https://pub.dev/documentation/mockito/latest/annotations/MockSpec-class.html).

Flutter Test Error - type 'Null' is not a subtype of type 'Future<Response>'

I am trying to create a simple test but I keep getting this error.
type 'Null' is not a subtype of type 'Future'
test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:async/async.dart';
import 'package:http/http.dart' as http;
import 'package:mocktail/mocktail.dart';
class MockClient extends Mock implements http.Client {}
void main() {
group('signin', () {
final client = MockClient();
final api = AuthApi('https://baseUrl', client);
final credential = Credential(
email: 'test#test.com',
type: AuthType.email,
password: 'pass',
);
test('should return error when status code is not 200', () async {
registerFallbackValue(Uri.parse(''));
when(() => client.post(any(), body: {}))
.thenAnswer((_) async => http.Response('{}', 404));
final result = await api.signIn(credential);
expect(result, isA<ErrorResult>());
});
});
}
Error is at line
final result = await api.signIn(credential); expect(result,
isA());
If I remove those lines I don't see the error.
auth_api.dart
class AuthApi implements IAuthApi {
AuthApi(this.baseUrl, this._client);
final http.Client _client;
String baseUrl;
#override
Future<Result<String>> signIn(Credential credential) async {
final endpoint = Uri.parse(baseUrl + '/auth/signin');
return await _postCredential(endpoint, credential);
}
#override
Future<Result<String>> signUp(Credential credential) async {
final endpoint = Uri.parse(baseUrl + '/auth/signup');
return await _postCredential(endpoint, credential);
}
Future<Result<String>> _postCredential(
Uri endpoint,
Credential credential,
) async {
final response =
await _client.post(endpoint, body: Mapper.toJson(credential));
if (response.statusCode != 200) {
return Result.error('Server Error');
}
var json = jsonDecode(response.body);
return json['auth_token'] != null
? Result.value(json['auth_token'])
: Result.error(json['message']);
}
}
I checked other similar question answers also but none of them worked. I am using mocktail package & http for post.
The problem is in that line:
when(() => client.post(any(), body: {}))
.thenAnswer((_) async => http.Response('{}', 404));
It means that when there's a client.post() method invoked with any() URL and a specific empty body {}, then it should return a mocked response.
What you want is to return a mocked response when there's any URL and any body, so it should be like this:
when(() => client.post(any(), body: any(named: 'body')))
.thenAnswer((_) async => http.Response('{}', 404));
However, if you want to test if a specific error is thrown, that code should be modified:
test('should return error when status code is not 200', () async {
when(() => client.post(any(), body: any(named: 'body')))
.thenThrow(ErrorResult(Exception()));
expect(() async => await api.signIn(credential),
throwsA(isA<ErrorResult>()));
});
First, you specify that calling API should throw an error (when(...).thenThrow(...)) and then you check if an error was thrown (expect(..., throwsA(...)))

The named parameter 'body' isn't defined + The named parameter 'header' isn't defined

I'm new to programming in general and very new to flutter, I get this following error message on both the "body" and "header" in the code which is marked in bold. I have tried everything I could find online for any help, but now found any solution, I figure this probobly isn't the hardest thing for someone who knows programming to solve, but I'm a beginner so I would really like the help. Thanks in advance.
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'model.dart';
const API_URL = 'https://todoapp-api-pyq5q.ondigitalocean.app';
const API_KEY = '7037674e-2262-4502-a2e1-29c940bd2a7a';
class Api {
static Future addTodoModel(TodoModel todo) async {
var json = todo.toJson();
var bodyString = jsonEncode(json);
var response = await http.post(Uri.parse('$API_URL/todos?key=$API_KEY',
**body: bodyString, headers:** {'Content-Type': 'application/json'}));
if (response.statusCode == 200) {
return response;
} else {
print('error on add');
return null;
}
}
static Future updateTodo(TodoModel todo, todoId) async {
var json = todo.toJson();
var bodyString = jsonEncode(json);
var response = await http.put(Uri.parse('$API_URL/todos/$todoId?key=$API_KEY',
**body: bodyString, headers:** {'Content-Type': 'application/json'}));
if (response.statusCode == 200) {
return response;
} else {
print('error on update');
return null;
}
}
static Future removeTodoModel(String todoId) async {
try {
var response = await http.delete(Uri.parse('$API_URL/todos/$todoId?key=$API_KEY'));
if (response.statusCode == 200) {
return response;
}
print('exception on remove');
} catch (exception) {
throw exception;
}
}
static Future<List<TodoModel>> getTodoModel() async {
try {
var response = await http.get(Uri.parse('$API_URL/todos?key=$API_KEY'));
var json = jsonDecode(response.body);
return json.map<TodoModel>((data) {
return TodoModel.fromJson(data);
}).toList();
} catch (exception) {
throw exception;
}
}
}
The Uri.parse funtion has no "header" or "body" parameter.
"headers" and "body" should be post method's params, like this:
Body and Headers are available in method of http.
For example:
import 'package:http/http.dart' as http;
// POST method
final response = await http.post(
url,
headers: {}, // Map<String*, String*>* headers
body: json.encode(params), // params is Map<String, dynamic>
);

I Want to get the token from my API by Dio flutter?

I'm trying to get my token from the API but it's empty
This is dio functions
import 'package:dio/dio.dart';
class DioHelper
{
static Dio dio;
static init()
{
print('dioHelper Initialized');
dio = Dio(
BaseOptions(
baseUrl:'my api link',
receiveDataWhenStatusError: true,
));
}
static Future<Response> getData ({
String url,
Map<String,dynamic> query,
String lang = 'en',
String token,
Map<String,dynamic> data,
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.get(
url,
queryParameters: query
);
}
static Future<Response> postData ({
String url,
Map<String,dynamic> query,
Map<String,dynamic> data,
String lang = 'ar',
String token
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.post(
url,
queryParameters: query,
data: data,
);
}
static Future<Response> putData ({
String url,
Map<String,dynamic> query,
Map<String,dynamic> data,
String lang = 'ar',
String token
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.put(
url,
queryParameters: query,
data: data,
);
}
static Future<Response> deleteData ({
String url,
String lang = 'ar',
String token
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.delete(url);
}
}
and pass value in this variable
String token = '';
and fuctions sharedPreferences
import 'package:shared_preferences/shared_preferences.dart';
class CacheHelper
{
static SharedPreferences sharedPreferences;
static init () async {
sharedPreferences = await SharedPreferences.getInstance();
}
static dynamic getData(String key, ){
return sharedPreferences.get(key);
}
static Future<bool> saveData({ String key, dynamic value})async{
if(value is String) return await sharedPreferences.setString(key, value);
if(value is int) return await sharedPreferences.setInt(key, value);
if(value is bool) return await sharedPreferences.setBool(key, value);
return await sharedPreferences.setDouble(key, value);
}
static Future<bool> removeData (String key)async{
return await sharedPreferences.remove(key);
}
}
*CALL THE TOKEN*
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
Bloc.observer = MyBlocObserver();
await DioHelper.init();
await CacheHelper.init();
token = CacheHelper.getData('token');
var IsLogin = CacheHelper.getData( 'IsLogin');
var IsBoarding = CacheHelper.getData( 'IsBoarding');
print(IsLogin);
print(IsBoarding);
print(token);
var widget;
if (IsBoarding != null) {
if (token == null) {
widget = ShopingScreen();
} else {
widget = Login_Screen();
}
} else {
widget = BordScreen();
}
THANKS
Is there any solution
I described my problem a few days ago, but without details, there was no useful solution
Tried a lot but it didn't solve this problem. I tried wiping the phone data or reformatting the codes and restarting the device several times.