Retrofit classes implemented with interceptor and base features

This commit is contained in:
2022-09-29 22:41:22 +01:00
parent d5a906d998
commit 057c6284ce
11 changed files with 53 additions and 18 deletions

View File

@@ -1,5 +1,6 @@
extension CurrencyExtension on String { extension CurrencyExtension on String {
/// Convert currency string into currency code
/// eg. "AUD - Australian Dollar" to "AUD"
String getCurrencyCode(){ String getCurrencyCode(){
return substring(0,3); return substring(0,3);
} }

View File

@@ -6,6 +6,7 @@ class Currency {
Currency(this.from, this.to, this.rate); Currency(this.from, this.to, this.rate);
} }
abstract class Mapper { /// Mapper class to convert any object to [Currency]
abstract class CurrencyMapper {
Currency convert(); Currency convert();
} }

View File

@@ -0,0 +1,15 @@
import 'package:dio/dio.dart';
class AppDio {
static Dio createDio() {
Dio dio = Dio(
BaseOptions(
receiveTimeout: 60000,
connectTimeout: 120000,
)
);
dio.interceptors.add(LogInterceptor());
return dio;
}
}

View File

@@ -3,6 +3,7 @@ import 'package:json_annotation/json_annotation.dart';
import 'package:retrofit/retrofit.dart'; import 'package:retrofit/retrofit.dart';
import '../model/Currency.dart'; import '../model/Currency.dart';
import 'app_dio.dart';
part 'backupCurrencyApi.g.dart'; part 'backupCurrencyApi.g.dart';
@@ -10,13 +11,18 @@ part 'backupCurrencyApi.g.dart';
abstract class BackupCurrencyApi { abstract class BackupCurrencyApi {
factory BackupCurrencyApi(Dio dio, {String baseUrl}) = _BackupCurrencyApi; factory BackupCurrencyApi(Dio dio, {String baseUrl}) = _BackupCurrencyApi;
static BackupCurrencyApi create() {
final dio = AppDio.createDio();
return _BackupCurrencyApi(dio);
}
@GET("latest?") @GET("latest?")
Future<HttpResponse<CurrencyResponse>> getCurrencyRate(@Query("from") String currencyFrom, Future<HttpResponse<CurrencyResponse>> getCurrencyRate(@Query("from") String currencyFrom,
@Query("to") String currencyTo); @Query("to") String currencyTo);
} }
@JsonSerializable() @JsonSerializable()
class CurrencyResponse implements Mapper{ class CurrencyResponse implements CurrencyMapper{
String? data; String? data;
double amount; double amount;
Map<String, double>? rates; Map<String, double>? rates;

View File

@@ -1,4 +1,6 @@
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:easy_cc_flutter/data/network/app_dio.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:retrofit/retrofit.dart'; import 'package:retrofit/retrofit.dart';
@@ -8,14 +10,21 @@ part 'currencyApi.g.dart';
@RestApi(baseUrl: "https://free.currencyconverterapi.com/api/v3/") @RestApi(baseUrl: "https://free.currencyconverterapi.com/api/v3/")
abstract class CurrencyApi { abstract class CurrencyApi {
factory CurrencyApi(Dio dio, {String baseUrl}) = _CurrencyApi; factory CurrencyApi(Dio dio) = _CurrencyApi;
static CurrencyApi create() {
final dio = AppDio.createDio();
dio.options.queryParameters.addAll({"apiKey": dotenv.env['apiKey']!});
return _CurrencyApi(dio);
}
@GET("/convert?") @GET("/convert?")
Future<HttpResponse<ResponseObject>> getConversion(@Query("apiKey") String apiKey, @Query("q") String currency); Future<HttpResponse<ResponseObject>> getConversion(@Query("q") String currency);
} }
@JsonSerializable() @JsonSerializable()
class ResponseObject implements Mapper{ class ResponseObject implements CurrencyMapper{
dynamic query; dynamic query;
Map<String, CurrencyObject>? results; Map<String, CurrencyObject>? results;

View File

@@ -11,7 +11,7 @@ mixin SafeApiCall {
HttpResponse<T> httpResponse = await apiCall; HttpResponse<T> httpResponse = await apiCall;
return httpResponse.data; return httpResponse.data;
} on DioError catch(dioError) { } on DioError catch(dioError) {
Map<String, dynamic>? errorResponse = dioError.response?.data; Map<String, dynamic>? errorResponse = dioError.response?.data?["error"];
String error; String error;
if (errorResponse?["error"] != null){ if (errorResponse?["error"] != null){
@@ -21,7 +21,6 @@ mixin SafeApiCall {
} else { } else {
error = "Failed to retrieve data from api"; error = "Failed to retrieve data from api";
} }
logger.e(dioError.error); logger.e(dioError.error);
throw HttpException(error); throw HttpException(error);

View File

@@ -4,7 +4,6 @@ import 'package:easy_cc_flutter/Utils/currencyUtils.dart';
import 'package:easy_cc_flutter/data/model/Currency.dart'; import 'package:easy_cc_flutter/data/model/Currency.dart';
import 'package:easy_cc_flutter/data/prefs/CurrencyPair.dart'; import 'package:easy_cc_flutter/data/prefs/CurrencyPair.dart';
import 'package:easy_cc_flutter/data/prefs/PreferenceProvider.dart'; import 'package:easy_cc_flutter/data/prefs/PreferenceProvider.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import '../../locator.dart'; import '../../locator.dart';
import '../../main.dart'; import '../../main.dart';
@@ -36,7 +35,7 @@ class RepositoryImpl extends Repository with SafeApiCall {
String currency = "${from}_$to"; String currency = "${from}_$to";
try { try {
ResponseObject responseObject = await getDataFromApiCall(_api.getConversion(dotenv.env['apiKey']!, currency)); ResponseObject responseObject = await getDataFromApiCall(_api.getConversion(currency));
return responseObject.convert(); return responseObject.convert();
} on HttpException catch(error) { } on HttpException catch(error) {
logger.e(error); logger.e(error);

View File

@@ -10,12 +10,9 @@ import 'data/prefs/PreferenceProvider.dart';
GetIt locator = GetIt.instance; GetIt locator = GetIt.instance;
void setupLocator() { void setupLocator() {
final dio = Dio();
locator.registerLazySingleton(() => PreferenceProvider()); locator.registerLazySingleton(() => PreferenceProvider());
locator.registerLazySingleton(() => CurrencyApi(dio)); locator.registerLazySingleton(() => CurrencyApi.create());
locator.registerLazySingleton(() => BackupCurrencyApi(dio)); locator.registerLazySingleton(() => BackupCurrencyApi.create());
locator.registerLazySingleton(() => RepositoryImpl()); locator.registerLazySingleton(() => RepositoryImpl());
locator.registerFactory(() => MainViewModel()); locator.registerFactory(() => MainViewModel());
} }

View File

@@ -162,6 +162,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.6" version: "4.0.6"
dio_logging_interceptor:
dependency: "direct main"
description:
name: dio_logging_interceptor
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
dropdown_search: dropdown_search:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -48,6 +48,7 @@ dependencies:
logger: ^1.1.0 logger: ^1.1.0
flutter_dotenv: ^5.0.2 flutter_dotenv: ^5.0.2
mockito: ^5.3.2 mockito: ^5.3.2
dio_logging_interceptor: ^1.0.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@@ -73,7 +73,7 @@ void main() {
// When // When
when(mockResponse.data).thenReturn(responseObject); when(mockResponse.data).thenReturn(responseObject);
when(currencyApi.getConversion(dotenv.env['apiKey']!, currency)) when(currencyApi.getConversion(currency))
.thenAnswer((_) async => mockResponse); .thenAnswer((_) async => mockResponse);
// Then // Then
@@ -91,7 +91,7 @@ void main() {
String currency = "AUD_GBP"; String currency = "AUD_GBP";
// When // When
when(currencyApi.getConversion(dotenv.env['apiKey']!, currency)) when(currencyApi.getConversion(currency))
.thenAnswer((_) async => Future.error(MockDioError())); .thenAnswer((_) async => Future.error(MockDioError()));
when(mockResponse.data).thenReturn(currencyResponse); when(mockResponse.data).thenReturn(currencyResponse);
when(backupCurrencyApi.getCurrencyRate("AUD", "GBP")) when(backupCurrencyApi.getCurrencyRate("AUD", "GBP"))
@@ -110,7 +110,7 @@ void main() {
// When // When
when(backUpError.error).thenReturn("Error message"); when(backUpError.error).thenReturn("Error message");
when(currencyApi.getConversion(dotenv.env['apiKey']!, currency)) when(currencyApi.getConversion(currency))
.thenAnswer((_) async => Future.error(MockDioError())); .thenAnswer((_) async => Future.error(MockDioError()));
when(backupCurrencyApi.getCurrencyRate("AUD", "GBP")) when(backupCurrencyApi.getCurrencyRate("AUD", "GBP"))
.thenAnswer((_) async => Future.error(backUpError)); .thenAnswer((_) async => Future.error(backUpError));