Developer

RESTful Networking

The package is built on Dio and offers additional functionality.

Features

Instead of the standard Dart HTTP Client for native platforms, we use cronet_http and cupertino_http with our custom package Native Dio on supported platforms like iOS, macOS, Android.

Additionally, the package sets up default configurations and enhances the Dio client through customization via config. It includes extra interceptors, such as a JWT token refresher, among others.

The package can also verify if the device is connected to the internet and if the server is accessible.

Installation

dart pub add eit_networking  --hosted-url=https://gitea.whitelabel.mobile.embedit.dev/api/packages/platform/pub/

!IMPORTANT You need access token for fetching from private pub repository. ELI add token automatically

Usage

Firstly, you must initialize ApiClient with your configuration.

final client = ApiClient.initialize(
    const ApiConfig('https://your-api.server/com'),
);

Configuration

ApiConfig

AttributeDefault valueDescription
baseUrlnone requiredBase url of your api server
connectionTimeout5s
receiveTimeout15s
useIsolatefalsejsonDecode in isolate
useNativetrueUse native if possible
debugfalselog to console
validateStatuses200, 201, 203, 205, 302status codes as validation
useConnectivitytrueNetwork change listener
checkInterval5speriodic check connectivity
interceptorsemptydio client interceptors
cacheConfigApiCacheConfig()cache configuration

ApiCacheConfig

AttributeDefault valueDescription
modeApiCacheMode.disabledBase url of your api server
dirnullDirectory for cached data
maxSize2MBMaximum size of the cache

Caching

The cache behavior is defined in ApiCacheConfig and adheres to the HTTP Cache-Control header.

There are 3 types of cache modes:

  1. Disabled (ApiCacheMode.disabled) - Disables caching. All requests will bypass any cache and fetch data directly from the network

On web, browser caches responses anyway

  1. Memory (ApiCacheMode.memory) - Caches responses in memory. This allows for faster access to the data but the cache will be cleared when the app is closed or when memory is needed.
  2. Disk (ApiCacheMode.disk) - Caches responses on disk. This provides persistent storage of cached data, which remains available even after the app is closed and reopened.

You have to specify "dir" in ApiCacheConfig

Requests

Requests are made using the Dio instance, which is accessible through ApiClient.

final dio = client.dio;

/// GET
final result = await dio.get<Map<String, dynamic>>('/endpoint');
/// POST
final result = await dio.post<Map<String, dynamic>>('/endpoint', data);
/// similarly for other HTTP request methods
...

Cancel Token

https://pub.dev/documentation/dio/latest/dio/CancelToken-class.html

The minimum flutter version for using it is 3.15. Below this version, Flutter throws errors while using a debugger.

Extensions

The package offers useful extensions for converting dynamic types, maps, and lists into typed objects. Additionally, it facilitates transformations into the Result type.

Future<Response>.request

final result = await dio.get<Map<String, dynamic>>('/endpoint')
    .request<SomeDto>(converter);
final processedResult = result.tryResult(onFailure, onSuccess)

FutureResponse.run - similar to request and tryResult

await dio.get<Map<String, dynamic>>('/endpoint')
    .run<SomeDto>(onFailure, onSuccess, converter);

How to use in Bloc

    /// Simple result mapper
    on<FetchEvent>((event, emit){
        dio.get<Map<String, dynamic>>('/endpoint')
            .request<MyEntity>(MyEntityX.fromDto).run(
                onSuccess: SuccessState.new,
                onFailure: FailureState.new,
            );
    })

Connectivity

The package provides the ability to listen to network changes or connection state through a ValueNotifier

How to use - widget

...
child: ValueListenableBuilder<NetworkConnectionStatus>(
        valueListenable: ApiClient.connectionState,
        builder: (BuildContext context, NetworkConnectionStatus state, Widget? child) {
            return Text('$state');
        },
),
...

How to use - cubit

/// Simply network cubit for update NetworkConnectionStatus
class NetworkCubit extends Cubit<NetworkConnectionStatus> {
  final ApiClient client;

  NetworkCubit(this.client) : super(NetworkConnectionStatus.empty()) {
    emit(client.connectionState.value);
    client.connectionState.addListener(_changeListener);
  }

  void _changeListener() => emit(client.connectionState.value);

  @override
  Future<void> close() {
    client.connectionState.removeListener(_changeListener);
    return super.close();
  }
}

...

child: BlocProvider(
    create:(context)=> NetworkCubit(context.read<ApiClient>()),
    child: Builder(context, state){
        return BlocBuilder<NetworkCubit, NetworkConnectionStatus>(
            builder: (context, state) {
                return Text('$state');
            }
        );
    }
)

Copyright © 2025. All rights reserved.