mirror of
https://github.com/hmalik144/easy_cc_flutter.git
synced 2025-12-10 03:05:34 +00:00
Retrofit classes implemented with interceptor and base features
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
15
lib/data/network/app_dio.dart
Normal file
15
lib/data/network/app_dio.dart
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
Reference in New Issue
Block a user