A comprehensive example demonstrating how to use SynqManager for offline-first task management.
- ✅ CRUD Operations — Create, read, update, and delete tasks
- ✅ Automatic Sync — Background synchronization every 30 seconds
- ✅ Manual Sync — Trigger sync on-demand with sync button
- ✅ Real-Time Updates — UI updates automatically on data changes
- ✅ Offline Support — Works without network connection
- ✅ Sync Status — Visual indicators for pending operations
- ✅ Conflict Resolution — Automatic conflict handling with last-write-wins
example/
├── lib/
│ ├── main.dart # Main app with TaskListScreen
│ ├── models/
│ │ └── task.dart # Task entity implementation
│ └── adapters/
│ ├── memory_local_adapter.dart # In-memory local storage
│ └── memory_remote_adapter.dart # In-memory remote storage
├── pubspec.yaml
└── README.md
-
Navigate to the example directory:
cd example -
Get dependencies:
flutter pub get
-
Run the app:
flutter run
The Task class implements SyncableEntity:
class Task implements SyncableEntity {
final String id;
final String userId;
final String title;
final bool completed;
final DateTime modifiedAt;
final DateTime createdAt;
final String version;
final bool isDeleted;
// Implement toJson, fromJson, copyWith...
}final manager = SynqManager<Task>(
localAdapter: MemoryLocalAdapter<Task>(fromJson: Task.fromJson),
remoteAdapter: MemoryRemoteAdapter<Task>(fromJson: Task.fromJson),
synqConfig: SynqConfig(
autoSyncInterval: const Duration(seconds: 30),
enableLogging: true,
defaultConflictResolver: LastWriteWinsResolver<Task>(),
),
);
await manager.initialize();
manager.startAutoSync(userId);// Listen to data changes
manager.onDataChange.listen((event) {
print('${event.changeType}: ${event.data.title}');
_loadTasks(); // Refresh UI
});
// Listen to sync progress
manager.onSyncProgress.listen((event) {
setState(() {
_syncStatus = 'Syncing: ${event.completed}/${event.total}';
});
});
// Listen to conflicts
manager.onConflict.listen((event) {
showSnackBar('Conflict detected: ${event.context.type}');
});// Create
await manager.save(newTask, userId);
// Read
final tasks = await manager.getAll(userId);
final task = await manager.getById(taskId, userId);
// Update
await manager.save(updatedTask, userId);
// Delete
await manager.delete(taskId, userId);// Manual sync
final result = await manager.sync(userId);
print('Synced: ${result.syncedCount}, Failed: ${result.failedCount}');
// Auto-sync
manager.startAutoSync(userId, interval: Duration(seconds: 30));
// Stop auto-sync
manager.stopAutoSync(userId: userId);The example uses an in-memory implementation for simplicity. In production:
- Use Hive for lightweight local storage
- Use SQLite for relational data
- Use SharedPreferences for simple key-value storage
The example simulates a remote server in-memory. In production:
- Use Firebase Firestore for real-time sync
- Use REST API with HTTP client
- Use GraphQL for flexible queries
To adapt this example for production:
- Replace adapters with real storage implementations
- Add authentication for user management
- Implement custom conflict resolvers for complex merge logic
- Add middleware for logging, analytics, or validation
- Configure retry strategies for network failures
- Add error handling and user feedback