A fully customizable offline-first sync engine for Flutter apps.
offline_sync_helper simplifies the process of working with local data, tracking changes, and syncing them with a remote backend. It offers built-in support for Hive, Drift, Firebase, and is extensible to any local storage system or API format.
Building apps that work offline and sync intelligently when online is a pain for most developers.
This package provides:
- β Easy offline storage integration
- β Automatic background sync when connectivity is restored
- β Customizable conflict resolution strategies
- β Full control over local/remote adapters and sync flows
- π Offline-first architecture
- π Automatic sync on app launch, connectivity change, or manual trigger
- π§ Change tracking for inserts, updates, deletes
- π οΈ Pluggable adapters for local and remote storage
- π§© Conflict resolution strategies: client wins, server wins, timestamp, or custom
- π Encrypted local storage support (via Hive)
- πΆ Connectivity-aware retry mechanism
- π§ͺ Testable architecture with mock support
- π€ Arabic & RTL support
Add the package to your pubspec.yaml:
dependencies:
offline_sync_helper: ^1.0.0
connectivity_plus: ^5.0.2
hive: ^2.2.3
http: ^1.2.1
path_provider: ^2.1.2You can replace Hive with Drift, Firebase, or other local storage plugins based on your adapter implementation.
import 'package:offline_sync_helper/offline_sync_helper.dart';
await OfflineSyncHelper.initialize(
localAdapter: HiveAdapter<Task>(),
remoteSyncService: ApiSyncService(),
conflictResolver: TimestampResolver(),
);await OfflineSyncHelper.save(
model: Task(id: 1, name: 'Collect Feedback'),
);The change is stored locally and synced automatically when the device goes online.
+-------------------+
| LocalAdapter |<------- Hive / Drift / Firebase
+-------------------+
|
βΌ
+-------------------+ +---------------------+
| SyncManager |<--------->| RemoteSyncService |
+-------------------+ +---------------------+
|
βΌ
+-------------------+
| ConflictResolver |<--- Custom, Timestamp, Client, Server
+-------------------+
abstract class LocalAdapter<T> {
Future<void> saveLocally(T model);
Future<List<T>> getPendingChanges();
Future<void> markAsSynced(List<T> models);
}abstract class RemoteSyncService<T> {
Future<SyncResult> sync(List<T> models);
}Built-in options:
ClientWinsResolverβ local data always overwrites remoteServerWinsResolverβ remote data always overwrites localTimestampResolverβ newer data (based on timestamp) wins
Create your own:
class CustomResolver implements ConflictResolver<Task> {
@override
Task resolve(Task local, Task remote) {
return local.priority > remote.priority ? local : remote;
}
}- App launch
- Internet reconnect
- Manual
syncNow()method - Periodic background task (coming soon)
Hive supports AES encryption. To enable:
var box = await Hive.openBox(
'tasks',
encryptionCipher: HiveAesCipher(my32ByteKey),
);OfflineSyncHelperConfig(
retryPolicy: RetryPolicy.maxAttempts(3),
batchSize: 20,
syncInterval: Duration(minutes: 5),
enableConnectivityWatcher: true,
autoSyncOnConnectivityChange: true,
);- β Android
- β iOS
Supports:
- RTL layouts
- Arabic and multi-language labels
intlpackage compatibility
| Use Case | Description |
|---|---|
| Field Agent App | Collect data in remote areas, sync later |
| Delivery Tracker | Update delivery statuses offline |
| E-Commerce Cart | Allow cart actions without internet |
| CRM / Lead Tracker | Sales staff update records offline |
π Full Example
For a complete working example with multiple field types, custom themes, and step-by-step forms, check out:
π Full Example on GitHub
MIT
sdkwala.com