mydomain
No ADS
No ADS

FlutterArtist Dio

  1. Dependencies
  2. FlutterArtistDio Configuration
  3. Example of using FlutterArtistDio
  4. FlutterArtistDio Overview
FlutterArtist DIO is a library, a wrapper of the DIO library package, that makes it easy to make Rest calls and log data. FlutterArtist DIO is part of the FlutterArtist project, but you can also use this library independently.
A log record generated by FlutterArtist DIO includes the following information:
  • Data source URL
  • Method (GET, POST,...)
  • Request-Headers and parameters
  • Authorization
  • Response-Headers, Response Time, Response Status, Error Info,...
  • Response-Body
FlutterArtistDio
class FlutterArtistDio {
  final ErrorInfoExtractor errorInfoExtractor;
  final Dio dio;

  FlutterArtistDio({
    required this.dio,
    this.errorInfoExtractor = const FlexibleErrorInfoExtractor(),
  });
	...
}	
The methods of FlutterArtist DIO typically return the Future<ApiResult<DATA>> data type:
  • If an error occurs: You can access the error information via the ApiResult.error property (FlutterArtist DIO automatically extracts the error to assign to ApiError.errorMessage and ApiError.errorDetails using a provided or default ErrorInfoExtractor).
  • If successful: You obtain the data through the ApiResult.data property (FlutterArtist DIO automatically converts the data into a Dart Object using a provided converter function).
class ApiResult<D> {
  final D? data;
  final int? statusCode;
  final String? statusMessage;
  final ApiError? error;
}

class ApiError extends AppError {
  ApiErrorType? errorType;
  int? statusCode;
  String? statusMessage;
  String? originErrorText;
  dynamic Function(Map<String, dynamic> value)? usedConverter;

  ApiError({
    this.statusCode,
    this.statusMessage,
    this.errorType,
    this.originErrorText,
    required super.errorMessage,
    super.errorDetails,
    this.usedConverter,
  });
}
No ADS
The real strength of FlutterArtist DIO lies in its ability to standardize server responses. In the real world, each API might return a different error structure, but through ErrorInfoExtractor, we unify them into a single ApiError format.
Rest Debug Viewer
You can view FlutterArtist DIO's logs through the built-in Rest Debug Viewer tool.
  • FlutterArtist Rest Debug Viewer
  • Giới thiệu về FlutterArtist
  • Download FlutterArtist Demo

1. Dependencies

Declare the necessary libraries in the pubspec.yaml file:
pubspec.yaml (*)
dependencies: 
  dio:  ^5.7.0  
  flutter_artist_dio:   
  json_serializable: ^6.11.1
  json_annotation: ^4.9.0
  fresh_dio: ^0.6.0

2. FlutterArtistDio Configuration

FlutterArtist Dio is created as part of the FlutterArtist ecosystem, so its configuration and usage are extremely streamlined. Here is how you initialize it in your application:
fa_dio.dart
// Create FlutterArtistDio to use in this Application.
final flutterArtistDio = _createFlutterArtistDio();

// For Download.
final flutterArtistDio4Download = _createFlutterArtistDio(
  bytesResponse: true,
);

// Optional: Using fresh_dio for Token management.
final fresh = Fresh.oAuth2<LoggedInUserData>(
  tokenStorage: TokenStorageImpl(),
  tokenHeader: (LoggedInUserData token) => {"Authorization": "Bearer ${token.accessToken}"},
  refreshToken: (LoggedInUserData? token, Dio client) {
    // Perform refresh logic here.
    throw UnimplementedError('Refresh token not supported yet!');
  },
);

FlutterArtistDio _createFlutterArtistDio({bool bytesResponse = false}) {
  final Dio _dio = bytesResponse
      ? Dio(BaseOptions(baseUrl: appBaseURL, responseType: ResponseType.bytes))
      : Dio(BaseOptions(baseUrl: appBaseURL));

  // Add interceptors for Auth and Logging.
  _dio.interceptors.add(fresh);
  _dio.interceptors.add(FlutterArtistDioLoggerInterceptor());

  return FlutterArtistDio(dio: _dio);
}
The flutterArtistDio and flutterArtistDio4Download objects can be accessed globally to be used anywhere in the application.
rest_config.dart
// Your app base URL:
const appBaseURL = "http://localhost:9090";

3. Example of using FlutterArtistDio

In this example, we will call a Rest API to receive JSON text and convert it into a Dart object using the CurrencyDataclass.
{
   "id": "USD",
   "name": "US Dollar",
   "symbol": "$", 
   "description": "The USD (United States dollar) ..."
}
Note: You should use json_serializable or dart_json_mapper for JSON serialization in Dart. Of the two, json_serializable is the "first-party" library maintained by Google.
currency_data.dart
@JsonSerializable()
class CurrencyData implements Identifiable<String> {
  @override
  @JsonKey(name: 'id')
  String id;

  @JsonKey(name: 'symbol')
  String symbol;

  @JsonKey(name: 'name')
  String name;

  @JsonKey(name: 'description')
  String? description;

  CurrencyData(this.id, this.symbol, this.name);

  CurrencyData.named({
    required this.id,
    required this.symbol,
    required this.name,
    this.description,
  });

  CurrencyInfo toCurrencyInfo() {
    return CurrencyInfo.named(id: id, name: name, symbol: symbol);
  }

  factory CurrencyData.fromJson(Map<String, dynamic> json) =>
      _$CurrencyDataFromJson(json);

  Map<String, dynamic> toJson() => _$CurrencyDataToJson(this);

  @override
  String toString() {
    return "${getClassName(this)}($id, $name)";
  }
}
The CurrencyRestProvider class will execute the API call:
CurrencyRestProvider
class CurrencyRestProvider { 

  // /rest/currency/VND
  Future<ApiResult<CurrencyData>> find({
    required String currencyId,
  }) async {
    Map<String, dynamic>? queryParameters = {};

    // /rest/currency/VND
    ApiResult<CurrencyData> result = await flutterArtistDio.jsonGet(
      "/rest/currency/$currencyId",
      queryParameters: queryParameters,
      converter: CurrencyData.fromMap,
    );
    return result;
  }

  ...
}
Finally, you handle the result safely:
final currencyRestProvider = CurrencyRestProvider();

ApiResult<CurrencyData> result = await currencyRestProvider.find(
  currencyId: "VND",
);

if (result.isError()) {
  print("Error Message: ${result.error?.errorMessage}");
  print("Error Details: ${result.error?.errorDetails}");
} else {
  CurrencyData? data = result.data;
  print("Currency Data: $data");
}
Another approach to handling the results of an API call:
final currencyRestProvider = CurrencyRestProvider();

ApiResult<CurrencyData> result = await currencyRestProvider.find(
  currencyId: "VND",
); 
// Throw ApiError
result.throwIfError(); 

CurrencyData? data = result.data;
print("Currency Data: $data");
  • FlutterArtist ApiResult

4. FlutterArtistDio Overview

The FlutterArtistDio class has a single constructor. The resulting object acts as an intelligent wrapper for a Dio instance, helping to manage network calls centrally and securely.
class FlutterArtistDio {
  final ErrorInfoExtractor errorInfoExtractor;
  final Dio dio;

  FlutterArtistDio({
    required this.dio,
    this.errorInfoExtractor = const FlexibleErrorInfoExtractor(),
  });
	...
}	
Here, ErrorInfoExtractor serves as a strategic "filter." Instead of letting raw error messages from the server disrupt the application's logic, this class is responsible for defining how error information is extracted. By default, FlutterArtistDio utilizes the FlexibleErrorInfoExtractor — a "magical" toolkit capable of automatically identifying and handling most of today's common JSON error formats, ranging from simple flat structures to complex nested ones.
Methods of FlutterArtistDio
Future<ApiResult<D>> jsonGet<D>(
    String path, { 
    required Converter<D>? converter,
    bool showDebug = false,
    //
    Object? data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onReceiveProgress, 
});

Future<ApiResult<D>> jsonPost<D>(
    String path, { 
    required Converter<D>? converter,
    bool showDebug = false,
    //
    Object? data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
});

Future<ApiResult<D>> jsonPut<D>(
    String path, { 
    required Converter<D>? converter,
    bool showDebug = false,
    //
    Object? data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
}); 

Future<ApiResult<D>> jsonDelete<D>(
    String path, { 
    required Converter<D>? converter,
    bool showDebug = false,
    //
    Object? data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
})

Future<ApiResult<List<int>?>> binaryGet(
  String path, {
  bool showDebug = false,
  //
  ProgressCallback? onReceiveProgress,
  Map<String, dynamic>? queryParameters,
  CancelToken? cancelToken,
  Object? data,
  Options? options,
})
No ADS

FlutterArtist

Show More
No ADS