From 057c6284cebc3c5823e2e582d1a0a6b8115481a7 Mon Sep 17 00:00:00 2001 From: hmalik144 Date: Thu, 29 Sep 2022 22:41:22 +0100 Subject: [PATCH 1/2] Retrofit classes implemented with interceptor and base features --- lib/Utils/currencyUtils.dart | 3 ++- lib/data/model/Currency.dart | 3 ++- lib/data/network/app_dio.dart | 15 +++++++++++++++ lib/data/network/backupCurrencyApi.dart | 8 +++++++- lib/data/network/currencyApi.dart | 15 ++++++++++++--- lib/data/network/safeApiCall.dart | 3 +-- lib/data/repository/RepositoryImpl.dart | 3 +-- lib/locator.dart | 7 ++----- pubspec.lock | 7 +++++++ pubspec.yaml | 1 + test/unit_test/repository_test.dart | 6 +++--- 11 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 lib/data/network/app_dio.dart diff --git a/lib/Utils/currencyUtils.dart b/lib/Utils/currencyUtils.dart index 8c424cf..fb739a6 100644 --- a/lib/Utils/currencyUtils.dart +++ b/lib/Utils/currencyUtils.dart @@ -1,5 +1,6 @@ extension CurrencyExtension on String { - + /// Convert currency string into currency code + /// eg. "AUD - Australian Dollar" to "AUD" String getCurrencyCode(){ return substring(0,3); } diff --git a/lib/data/model/Currency.dart b/lib/data/model/Currency.dart index 91b1779..8aac23d 100644 --- a/lib/data/model/Currency.dart +++ b/lib/data/model/Currency.dart @@ -6,6 +6,7 @@ class Currency { Currency(this.from, this.to, this.rate); } -abstract class Mapper { +/// Mapper class to convert any object to [Currency] +abstract class CurrencyMapper { Currency convert(); } \ No newline at end of file diff --git a/lib/data/network/app_dio.dart b/lib/data/network/app_dio.dart new file mode 100644 index 0000000..1a303a0 --- /dev/null +++ b/lib/data/network/app_dio.dart @@ -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; + } +} \ No newline at end of file diff --git a/lib/data/network/backupCurrencyApi.dart b/lib/data/network/backupCurrencyApi.dart index a2dceba..cbc67a3 100644 --- a/lib/data/network/backupCurrencyApi.dart +++ b/lib/data/network/backupCurrencyApi.dart @@ -3,6 +3,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:retrofit/retrofit.dart'; import '../model/Currency.dart'; +import 'app_dio.dart'; part 'backupCurrencyApi.g.dart'; @@ -10,13 +11,18 @@ part 'backupCurrencyApi.g.dart'; abstract class BackupCurrencyApi { factory BackupCurrencyApi(Dio dio, {String baseUrl}) = _BackupCurrencyApi; + static BackupCurrencyApi create() { + final dio = AppDio.createDio(); + return _BackupCurrencyApi(dio); + } + @GET("latest?") Future> getCurrencyRate(@Query("from") String currencyFrom, @Query("to") String currencyTo); } @JsonSerializable() -class CurrencyResponse implements Mapper{ +class CurrencyResponse implements CurrencyMapper{ String? data; double amount; Map? rates; diff --git a/lib/data/network/currencyApi.dart b/lib/data/network/currencyApi.dart index 907e2b2..1523eec 100644 --- a/lib/data/network/currencyApi.dart +++ b/lib/data/network/currencyApi.dart @@ -1,4 +1,6 @@ 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:retrofit/retrofit.dart'; @@ -8,14 +10,21 @@ part 'currencyApi.g.dart'; @RestApi(baseUrl: "https://free.currencyconverterapi.com/api/v3/") 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?") - Future> getConversion(@Query("apiKey") String apiKey, @Query("q") String currency); + Future> getConversion(@Query("q") String currency); } @JsonSerializable() -class ResponseObject implements Mapper{ +class ResponseObject implements CurrencyMapper{ dynamic query; Map? results; diff --git a/lib/data/network/safeApiCall.dart b/lib/data/network/safeApiCall.dart index 08f0373..f8150eb 100644 --- a/lib/data/network/safeApiCall.dart +++ b/lib/data/network/safeApiCall.dart @@ -11,7 +11,7 @@ mixin SafeApiCall { HttpResponse httpResponse = await apiCall; return httpResponse.data; } on DioError catch(dioError) { - Map? errorResponse = dioError.response?.data; + Map? errorResponse = dioError.response?.data?["error"]; String error; if (errorResponse?["error"] != null){ @@ -21,7 +21,6 @@ mixin SafeApiCall { } else { error = "Failed to retrieve data from api"; } - logger.e(dioError.error); throw HttpException(error); diff --git a/lib/data/repository/RepositoryImpl.dart b/lib/data/repository/RepositoryImpl.dart index d085a00..9b53afc 100644 --- a/lib/data/repository/RepositoryImpl.dart +++ b/lib/data/repository/RepositoryImpl.dart @@ -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/prefs/CurrencyPair.dart'; import 'package:easy_cc_flutter/data/prefs/PreferenceProvider.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; import '../../locator.dart'; import '../../main.dart'; @@ -36,7 +35,7 @@ class RepositoryImpl extends Repository with SafeApiCall { String currency = "${from}_$to"; try { - ResponseObject responseObject = await getDataFromApiCall(_api.getConversion(dotenv.env['apiKey']!, currency)); + ResponseObject responseObject = await getDataFromApiCall(_api.getConversion(currency)); return responseObject.convert(); } on HttpException catch(error) { logger.e(error); diff --git a/lib/locator.dart b/lib/locator.dart index ab9041e..856e4f7 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -10,12 +10,9 @@ import 'data/prefs/PreferenceProvider.dart'; GetIt locator = GetIt.instance; void setupLocator() { - final dio = Dio(); - locator.registerLazySingleton(() => PreferenceProvider()); - locator.registerLazySingleton(() => CurrencyApi(dio)); - locator.registerLazySingleton(() => BackupCurrencyApi(dio)); + locator.registerLazySingleton(() => CurrencyApi.create()); + locator.registerLazySingleton(() => BackupCurrencyApi.create()); locator.registerLazySingleton(() => RepositoryImpl()); locator.registerFactory(() => MainViewModel()); - } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index d576ccc..49e5602 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -162,6 +162,13 @@ packages: url: "https://pub.dartlang.org" source: hosted 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: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 6e3d8f1..34c05c3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: logger: ^1.1.0 flutter_dotenv: ^5.0.2 mockito: ^5.3.2 + dio_logging_interceptor: ^1.0.1 dev_dependencies: flutter_test: diff --git a/test/unit_test/repository_test.dart b/test/unit_test/repository_test.dart index 6831e92..aae9c06 100644 --- a/test/unit_test/repository_test.dart +++ b/test/unit_test/repository_test.dart @@ -73,7 +73,7 @@ void main() { // When when(mockResponse.data).thenReturn(responseObject); - when(currencyApi.getConversion(dotenv.env['apiKey']!, currency)) + when(currencyApi.getConversion(currency)) .thenAnswer((_) async => mockResponse); // Then @@ -91,7 +91,7 @@ void main() { String currency = "AUD_GBP"; // When - when(currencyApi.getConversion(dotenv.env['apiKey']!, currency)) + when(currencyApi.getConversion(currency)) .thenAnswer((_) async => Future.error(MockDioError())); when(mockResponse.data).thenReturn(currencyResponse); when(backupCurrencyApi.getCurrencyRate("AUD", "GBP")) @@ -110,7 +110,7 @@ void main() { // When when(backUpError.error).thenReturn("Error message"); - when(currencyApi.getConversion(dotenv.env['apiKey']!, currency)) + when(currencyApi.getConversion(currency)) .thenAnswer((_) async => Future.error(MockDioError())); when(backupCurrencyApi.getCurrencyRate("AUD", "GBP")) .thenAnswer((_) async => Future.error(backUpError)); From 08927ee0f89f20862cfc21bdf41ea0ec0cb7bb8e Mon Sep 17 00:00:00 2001 From: hmalik144 Date: Thu, 29 Sep 2022 22:48:08 +0100 Subject: [PATCH 2/2] Remove dio_logging_interceptor from pubspec.yaml --- pubspec.lock | 7 ------- pubspec.yaml | 1 - 2 files changed, 8 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 49e5602..d576ccc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -162,13 +162,6 @@ packages: url: "https://pub.dartlang.org" source: hosted 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: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 34c05c3..6e3d8f1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,7 +48,6 @@ dependencies: logger: ^1.1.0 flutter_dotenv: ^5.0.2 mockito: ^5.3.2 - dio_logging_interceptor: ^1.0.1 dev_dependencies: flutter_test: