Asset Manager Library

A lightweight Flutter/Dart asset management library that supports downloading, verifying, caching, and syncing files from REST or GraphQL endpoints.
It’s designed for applications that need reliable offline asset persistence, such as games, media apps, or travel experiences.


Features

  • ✅ Concurrent multi-file downloads
  • ✅ Retry logic with exponential backoff
  • ✅ Progress, completion, and failure callbacks
  • ✅ Local caching under app documents directory (<app-docs>/assets/<path>)
  • ✅ Syncs local DB with actual files on disk
  • ✅ Simple, testable architecture (no native dependencies)
  • ✅ Works with REST or GraphQL backends (via urlResolver)

Installation

Add dependencies to your pubspec.yaml:

dependencies:
  dio: ^5.7.0
  path_provider: ^2.1.3
  path: ^1.9.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  test: ^1.25.0
  dio_http_mock_adapter: ^0.6.1
  mockito: ^5.4.4

Quick Start

Define your AppAsset model

class AppAsset {
  final String id;
  final String path;
  final String? url;
  final String? downloadUrl;
  final int? totalSize;

  AppAsset({
    required this.id,
    required this.path,
    this.url,
    this.downloadUrl,
    this.totalSize,
  });

  factory AppAsset.fromJson(Map<String, dynamic> json) => AppAsset(
    id: json['id'],
    path: json['path'],
    url: json['url'],
    downloadUrl: json['downloadUrl'],
    totalSize: json['totalSize'],
  );

  Map<String, dynamic> toJson() => {
    'id': id,
    'path': path,
    'url': url,
    'downloadUrl': downloadUrl,
    'totalSize': totalSize,
  };
}

Download Assets Using AssetLoader

await AssetLoader.downloadAssetList(
  assets: myAssets,
  urlResolver: (a) => a.url ?? a.downloadUrl ?? '',
  concurrency: 3,
  retryAttempts: 3,
  onFileProgress: (asset, p) => print("${asset.path}: ${(p * 100).toStringAsFixed(1)}%"),
  onFileCompleted: (asset, msg) => print(msg),
  onFileFailed: (asset, err) => print("Failed ${asset.path}: $err"),
  onOverallProgress: (done, total) => print("Progress: $done/$total"),
  onAllCompleted: () => print("✅ All done!"),
);

Files are saved to <AppDocumentsDir>/assets/<asset.path>.


High-Level Use with AssetManagerDownloader

final downloader = AssetManagerDownloader()
  ..onBeforeAssetsDownloaded = () async => print("Preparing downloads...");

await downloader.downloadAssets(
  myAssets,
  onProgress: (progress, asset, msg) => print(msg),
  onFileCompleted: (asset, msg) => print('OK: ${asset.path}'),
  onFileFailed: (asset, err) => print('FAIL: ${asset.path} $err'),
  onOverallProgress: (msg) => print(msg),
  onAllCompleted: (msg) => print(msg),
  onRetry: (msg, failed) => print('Retrying ${failed.length} assets...'),
);

This wrapper:

  • Syncs with your local database (via LocalStorage).
  • Deletes invalid entries when files are missing.
  • Tracks total bytes and overall progress.

🔍 Check Required Assets

final allDownloaded = await downloader.isRequiredAssetsDownloaded();
if (!allDownloaded) {
  print("Some assets are missing!");
}

This checks the assets listed in your AssetRegister and verifies all are downloaded.


Project Structure

lib/
 ├── persistance/
 │    └── file_handler.dart
 ├── services/
 │    └── asset_management/
 │         ├── asset_loader.dart
 │         └── asset_downloader.dart
 └── register/
      └── asset_register.dart

Extending

Add Checksum Verification (Optional)

Add a hash field to AppAsset and compute its MD5 or SHA-256 after download to ensure file integrity.

Add Resume Support (Optional)

If your backend supports range requests, add the Range header for partial downloads.


Example Integration with a REST API

final response = await Dio().get("https://api.example.com/assets");
final assets = (response.data as List)
    .map((a) => AppAsset.fromJson(a))
    .toList();

await AssetLoader.downloadAssetList(
  assets: assets,
  urlResolver: (a) => a.url ?? '',
);

Utility Classes

  • FileHandler → JSON cache handler with checkFilesExist().
  • LocalStorage → Local DB wrapper for asset persistence.
  • AssetLoader → Core downloader, retry logic, progress events.
  • AssetManagerDownloader → High-level manager with DB + disk sync.

License

MIT License
© 2025 Olamide Ogunlade