Skip to content

Commit

Permalink
feat: Added example network request with retrofit (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
utpal-barman authored Oct 4, 2024
1 parent 540a327 commit d9aeb69
Show file tree
Hide file tree
Showing 41 changed files with 357 additions and 129 deletions.
8 changes: 8 additions & 0 deletions .run/Development Debug.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Development Debug" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="additionalArgs" value="--dart-define-from-file=lib/config/dart_define_keys/dart_define_development_keys.json" />
<option name="buildFlavor" value="development" />
<option name="filePath" value="$PROJECT_DIR$/lib/main_development.dart" />
<method v="2" />
</configuration>
</component>
8 changes: 8 additions & 0 deletions .run/Development Release.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Development Release" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="additionalArgs" value="--release --dart-define-from-file=lib/config/dart_define_keys/dart_define_development_keys.json" />
<option name="buildFlavor" value="development" />
<option name="filePath" value="$PROJECT_DIR$/lib/main_development.dart" />
<method v="2" />
</configuration>
</component>
4 changes: 3 additions & 1 deletion .run/staging_debug.run.xml → .run/Staging Debug.run.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Staging Debug" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="additionalArgs" value="--dart-define-from-file=lib/config/dart_define_keys/dart_define_staging_keys.json" />
<option name="buildFlavor" value="staging" />
<option name="filePath" value="$PROJECT_DIR$/lib/main_staging.dart" />
<method v="2" />
</configuration>
</component>
</component>
5 changes: 3 additions & 2 deletions .run/staging_release.run.xml → .run/Staging Release.run.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Staging Release" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="additionalArgs" value="--release" />
<option name="additionalArgs" value="--release --dart-define-from-file=lib/config/dart_define_keys/dart_define_staging_keys.json" />
<option name="buildFlavor" value="staging" />
<option name="filePath" value="$PROJECT_DIR$/lib/main_staging.dart" />
<method v="2" />
</configuration>
</component>
</component>
6 changes: 0 additions & 6 deletions .run/development_debug.run.xml

This file was deleted.

7 changes: 0 additions & 7 deletions .run/development_release.run.xml

This file was deleted.

27 changes: 12 additions & 15 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,24 @@
"request": "launch",
"type": "dart",
"program": "lib/main_development.dart",
"args": ["--flavor", "development"]
"args": [
"--flavor",
"development",
"--dart-define-from-file",
"lib/config/dart_define_keys/dart_define_development_keys.json"
]
},
{
"name": "Staging",
"request": "launch",
"type": "dart",
"program": "lib/main_staging.dart",
"args": ["--flavor", "staging"]
"args": [
"--flavor",
"staging",
"--dart-define-from-file",
"lib/config/dart_define_keys/dart_define_staging_keys.json"
]
}

// Commented to avoid running the product app from VSCode
// Uncomment only if we really need it
// {
// "name": "Production",
// "request": "launch",
// "type": "dart",
// "program": "lib/main_production.dart",
// "args": [
// "--flavor",
// "production"
// ]
// },
]
}
83 changes: 62 additions & 21 deletions .vscode/ml-flutter.code-snippets
Original file line number Diff line number Diff line change
@@ -1,22 +1,63 @@
{
"Freezed Class": {
"prefix": "freezed",
"body": [
"import 'package:freezed_annotation/freezed_annotation.dart';",
"",
"part '${1:file}.freezed.dart';",
"part '${1:file}.g.dart';",
"",
"@freezed",
"class ${2:ClassName} with _$${2:ClassName} {",
" const factory ${2:ClassName}({",
" required ${0:param},",
" }) = _${2:ClassName};",
"",
" factory ${2:ClassName}.fromJson(Map<String, dynamic> json) =>",
" _$${2:ClassName}FromJson(json);",
"}"
],
"description": "Creates basement for a freezed class."
},
}
"Remote Data Source": {
"prefix": "remote_data_source",
"description": "Snippet for quick creation of a remote data source.",
"body": [
"import 'package:dio/dio.dart';",
"import 'package:flutter_template/injection/network_module.dart';",
"import 'package:injectable/injectable.dart';",
"import 'package:retrofit/retrofit.dart';",
"",
"part '$TM_FILENAME_BASE.g.dart';",
"",
"@RestApi()",
"@lazySingleton",
"abstract class ${2:Scope}RemoteDataSource {",
" @factoryMethod",
" factory $2RemoteDataSource(",
" @Named(dioAuthenticated) Dio dio,",
" ) = _$2RemoteDataSource;",
"",
" ${3:/* Fill your calls here */}",
"}",
""
]
},
"Freezed Class": {
"prefix": "freezed",
"body": [
"import 'package:freezed_annotation/freezed_annotation.dart';",
"",
"part '${1:file}.freezed.dart';",
"part '${1:file}.g.dart';",
"",
"@freezed",
"class ${2:ClassName} with _$${2:ClassName} {",
" const factory ${2:ClassName}({",
" required ${0:param},",
" }) = _${2:ClassName};",
"",
" factory ${2:ClassName}.fromJson(Map<String, dynamic> json) =>",
" _$${2:ClassName}FromJson(json);",
"}"
],
"description": "Creates basement for a freezed class."
},
"Remapper": {
"prefix": "remapper",
"description": "Create a basement for a remapper class.",
"body": [
"import 'package:injectable/injectable.dart';",
"",
"@lazySingleton",
"class ${1:Entity}Remapper {",
" ${1:Entity}Entity fromResponse(${1:Entity}Response response) {",
" return ${1:Entity}Entity(",
" ${2}",
" );",
" }",
"",
"}"
]
}
}
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="${appName}"
android:name="${applicationName}"
Expand Down
15 changes: 14 additions & 1 deletion build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ targets:
json_serializable:
options:
explicit_to_json: true
# By deafult, field_rename: none, More options —
# By default, field_rename: none, More options —
# snake, kebab, pascal, etc. To use, uncomment this below line —
# field_rename: snake
generate_for:
include:
# data layer:
- lib/data/model/**.dart
- lib/data/services/**_request.dart
- lib/data/services/**_response.dart
- lib/data/response_objects/**.dart

# domain layer:
Expand All @@ -20,13 +22,21 @@ targets:
# We should not allow the entire `/entities` folder here, as entities don't need fromJson(), toJson(), etc.
# Specifying exact file will help build runner to run fast.
- lib/domain/entities/user.dart

# Retrofit Classes / Remote Data Sources
retrofit_generator:
generate_for:
include:
- lib/data/**/data_sources/remote/*_remote_data_source.dart

# Data Classes, Cloning
freezed:freezed:
generate_for:
include:
# data layer:
- lib/data/model/**.dart
- lib/data/services/**_request.dart
- lib/data/services/**_response.dart
- lib/data/response_objects/**.dart

# domain layer:
Expand All @@ -46,9 +56,12 @@ targets:
generate_for:
include:
- lib/injection/injector.dart
- lib/injection/modules/*_module.dart

# data
- lib/data/**_config.dart
- lib/data/**_client.dart
- lib/data/**/data_sources/remote/*_remote_data_source.dart
- lib/data/services/**_service_impl.dart
- lib/data/services/**_remapper.dart
- lib/data/preferences/**_preferences.dart
Expand Down
5 changes: 5 additions & 0 deletions lib/config/dart_define.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This class is declared as an `abstract interface` to restrict inheritance
// and prevent instantiation outside the library.
abstract interface class DartDefine {
static const apiBaseUrl = String.fromEnvironment('API_BASE_URL');
}
3 changes: 3 additions & 0 deletions lib/config/dart_define_keys/dart_define_development_keys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"API_BASE_URL": "https://randomuser.me"
}
3 changes: 3 additions & 0 deletions lib/config/dart_define_keys/dart_define_production_keys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"API_BASE_URL": "https://randomuser.me"
}
3 changes: 3 additions & 0 deletions lib/config/dart_define_keys/dart_define_staging_keys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"API_BASE_URL": "https://randomuser.me"
}
12 changes: 7 additions & 5 deletions lib/data/api/api_config.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'package:injectable/injectable.dart';

@Injectable()
/// A configuration class providing properties specific to an API.
///
/// Class instance is registered via [ApiConfigModule].
class ApiConfig {
final String baseUrl;
ApiConfig({
required this.baseUrl,
});

ApiConfig(this.baseUrl);
final String baseUrl;

String get apiUrl => '$baseUrl/api';
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'package:dio/dio.dart';
import 'package:flutter_template/data/response_objects/response_error.dart';
import 'package:flutter_template/data/services/http_client/http_client.dart';
import 'package:flutter_template/data/core/http_client/http_client.dart';
import 'package:flutter_template/domain/common/response_error/response_error.dart';
import 'package:flutter_template/injection/modules/network_module.dart';
import 'package:injectable/injectable.dart';

/// Abstraction of the Dio http client class.
@Injectable(as: HttpClient)
class DioHttpClient extends HttpClient {
DioHttpClient(this.dio);
DioHttpClient(@Named(dioForAuthentication) this.dio);

final Dio dio;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:dio/dio.dart';
import 'package:flutter_template/data/services/http_client/dio_http_client.dart';
import 'package:flutter_template/data/core/http_client/dio_http_client.dart';

DioHttpClient? _dioClient;

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_template/data/interceptor/meta_interceptor.dart';
import 'package:flutter_template/data/core/http_client/dio_http_client.dart';
import 'package:flutter_template/data/core/http_client/http_client.dart';
import 'package:flutter_template/data/interceptors/meta_interceptor.dart';
import 'package:flutter_template/data/model/auth/auth_tokens.dart';
import 'package:flutter_template/data/preferences/auth_preferences.dart';
import 'package:flutter_template/data/response_objects/response_error.dart';
import 'package:flutter_template/data/response_objects/tokens_response.dart';
import 'package:flutter_template/data/services/http_client/dio_http_client.dart';
import 'package:flutter_template/data/services/http_client/http_client.dart';
import 'package:flutter_template/domain/common/response_error/response_error.dart';
import 'package:flutter_template/domain/preferences/user_preferences.dart';

class AuthInterceptor extends InterceptorsWrapper {
class AuthInterceptor extends QueuedInterceptor {
AuthInterceptor({
required this.httpClient,
required this.onTokenExpired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter_template/presentation/app_flavor.dart';
import 'package:package_info_plus/package_info_plus.dart';

class MetaInterceptor extends InterceptorsWrapper {
class MetaInterceptor extends QueuedInterceptor {
MetaInterceptor(this.flavor);

static String nMetaHeaderKey = 'n-meta';
Expand Down
4 changes: 2 additions & 2 deletions lib/data/preferences/user_shared_preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import 'package:shared_preferences/shared_preferences.dart';

/// Store the current authenticated user's basic information.
@LazySingleton()
class UserSharedPreferences extends UserPreferences {
@LazySingleton(as: UserPreferences)
class UserSharedPreferences implements UserPreferences {
UserSharedPreferences(this._preferences);

final SharedPreferences _preferences;
Expand Down
4 changes: 2 additions & 2 deletions lib/data/response_objects/error_response.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:flutter_template/data/response_objects/response_error.dart';
import 'package:flutter_template/domain/common/response_error/response_error.dart';
import 'package:flutter_template/nstack/nstack.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

Expand Down Expand Up @@ -55,7 +55,7 @@ extension ErrorResponseExtensions on ErrorResponse {
extension ErrorNameExtensions on ErrorName {
String getErrorMessage(Localization l10n) {
switch (this) {
//Handle error enum and return mapped nstack vlaue
//Handle error enum and return mapped nstack value
case ErrorName.errorExample:
return l10n.error.authenticationError;
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:dio/dio.dart';
import 'package:flutter_template/data/services/profile/dtos/profile_response.dart';
import 'package:flutter_template/injection/modules/network_module.dart';
import 'package:injectable/injectable.dart';
import 'package:retrofit/retrofit.dart';

part 'profile_remote_data_source.g.dart';

@RestApi()
@lazySingleton
abstract class ProfileRemoteDataSource {
@factoryMethod
factory ProfileRemoteDataSource(
@Named(dioAuthenticated) Dio dio,
) = _ProfileRemoteDataSource;

@GET('/')
Future<ProfileResponse> getProfile();
}
Loading

0 comments on commit d9aeb69

Please sign in to comment.