kickin_network 0.0.1-dev.19 copy "kickin_network: ^0.0.1-dev.19" to clipboard
kickin_network: ^0.0.1-dev.19 copied to clipboard

Kickin network provides utilities to handle network efficiently and reliably

kickin_network #experimental #

Kickin is a modern modular toolkit designed to turbocharge your Flutter development and eliminate boilerplate. It provides curated utilities, elegant extensions, and standardized architectures for common tasks like networking, state management, and storage.

This is the #network part of it.


โœจ What's in the box #

Feature Description
KRestApiBase Singleton-friendly API root with shared Dio, base URL, logging
KApiCacheMixin mixin Opt-in in-memory cache with optional Hive persistence
KApiMonitorMixin mixin Internet connectivity monitoring with listener management
KRestApi<T> Typed API client module with scoped cache and base URL access
KRestRequest Composable, cloneable HTTP request with full Dio feature coverage
KResponse<T> Structured response wrapper with typed success and error paths
LogOptions Configurable request/response logging for debug workflows

๐ŸŒ Network #

A unified layer for all remote communication, adaptable to different protocols.

REST APIs #

A robust and extensible wrapper over Dio for HTTP requests with structured error handling, caching, logging, and decoding.

Key classes: KRestApiBase, KRestApi, KRestRequest, KResponse

Request capabilities

  • Choose between a primary Dio client and an external Dio client per request.
  • Use tryโ€ฆ request methods to capture failures as KResponse instead of throwing.
  • Clone and transform requests with copyWith, toGetRequest, toPostRequest, toPutRequest, toPatchRequest, toDeleteRequest, toDownloadRequest, and toRequest.
  • Prefix endpoints with a shared base URL, or opt out per request with useBaseUrl: false.
  • Log requests and responses with configurable LogOptions.
  • Download files with custom savePath, fileAccessMode, and deleteOnError behaviour.

Caching โ€” KApiCacheMixin mixin

Cache is opt-in via a mixin. Apply KApiCacheMixin to your API root to unlock per-client in-memory caching, with optional persistence through kickin_storage.

class MyApi extends KRestApiBase with KApiCacheMixin {
  static final shared = MyApi._();
  MyApi._();
}

Each KRestApi client gets a scoped cache key (parentType_clientType) so there are zero conflicts across clients. Override id if you mount multiple instances of the same client type on the same root.

Cache is flushed to Hive in a debounced batch (300 ms) to keep write pressure low. On cold start, the stored key index is used to hydrate the in-memory map before any request fires.

// Inside a KRestApi subclass
setCache(someValue);      // write
cache;                    // read (typed via KRestApi<T>)
clearCache();             // scoped delete โ€” only this client's entry

Enable persistence in intialize:

await MyApi.shared.intialize(
  syncCacheToStorage: true,
  cacheBoxName: 'my_app_cache', // optional, defaults to 'kickin_api_cache'
);

Connectivity monitoring โ€” KApiMonitorMixin mixin

Apply KApiMonitorMixin to subscribe to internet status changes anywhere in the app via your API singleton.

class MyApi extends KRestApiBase with KApiCacheMixin, KApiMonitorMixin { ... }

// Start/stop globally
MyApi.shared.startMonitoring();
MyApi.shared.stopMonitoring();

// Register a typed listener
MyApi.shared.addListener((InternetStatus status) {
  if (status == InternetStatus.disconnected) showOfflineBanner();
});

// Remove it when done
MyApi.shared.removeListener(myListener);

Listeners are paused (not cancelled) by stopMonitoring, so they resume cleanly without re-registration. An internal debug subscription logs status changes when monitorActivities is enabled.

Disposal

@override
void dispose() {
  MyApi.shared.disposeCache();     // cancels pending flush timer
  MyApi.shared.disposeMonitor();   // cancels all subscriptions
}

Usage #

import 'package:kickin_network/kickin_network.dart';

class MyApi extends KRestApiBase with KApiCacheMixin, KApiMonitorMixin {
  MyApi._();
  static final shared = MyApi._();

  late final users = UsersApi(this);
  
  // @override
  // Object? globalErrorOverride(dynamic data, Object? error, [StackTrace? st]) {
  // if (error == null) return null;
  //  if (error is Map && error.containsKey("error")) return error;
  //  return null;
  // }
}

class UsersApi extends KRestApi<Map<String, dynamic>> {
  UsersApi(super.parent);

  late final getUser = KGetRequest<Map<String, dynamic>>(
    this,
    path: '/user',
    decoder: (data, _) => data as Map<String, dynamic>,
  );

  Future<Map<String, dynamic>?> fetchUser() async {
    // Return cached value if available
    if (cache != null) return cache;

    final result = await getUser.copyWith(
      headers: await loadAuthHeaders(),
    ).send();

    // OR
    // final apiResult = await getUser.copyWith(
    // headers: await loadAuthHeaders(),
    // ).sendResult()
    // We can then access apiResult.value or apiResult.error
    // errors can be overriden in KRestApiBase or set in the KRestRequest
    // e.g 
    

    if (result != null) setCache(result);
    return result;
  }
  
}

Future<void> main() async {
  await MyApi.shared.intialize(
    baseUrl: 'https://api.myapp.com',
    syncCacheToStorage: true,
    logOptions: LogOptions.debugAll(),
  );

  MyApi.shared.startMonitoring();
  MyApi.shared.primaryInterceptors.add((...){
    log("some interception");
  });

  final user = await MyApi.shared.users.fetchUser();
  print(user);
}

Example requests #

final api = MyApi.shared;

// Safe โ€” returns null instead of throwing
final profile = await api.users.getUser.tryGet();

// Clone with a path transform
final updated = await api.users.getUser.copyWith(
  pathTransform: (path) => '$path/profile',
).get();

๐Ÿ“ฑ Platform setup #

Required only when using connectivity monitoring (KApiMonitorMixin).

Android #

Add permissions to android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  ...

macOS #

Add the network entitlement to macos/Runner/DebugProfile.entitlements and macos/Runner/Release.entitlements:

<plist version="1.0">
  <dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
  </dict>
</plist>

Note: The correct entitlement for outbound HTTP is network.client, not network.server.


๐Ÿ“ฆ Installation #

flutter pub add kickin_network

Or add manually to pubspec.yaml:

dependencies:
  kickin_network: 0.0.1-dev.19

Dependencies: dio ยท internet_connection_checker_plus ยท kickin_storage

Other network kinds (WebSocket, GraphQL) are on the way.

0
likes
0
points
485
downloads

Publisher

unverified uploader

Weekly Downloads

Kickin network provides utilities to handle network efficiently and reliably

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

dio, flutter, internet_connection_checker_plus, kickin_storage, logger

More

Packages that depend on kickin_network