What is BLoC Offline Support?
Offline support in BLoC refers to the ability to persist your app’s state and queue user actions (like adding, editing, or deleting data) when the device is offline. Once connectivity is restored, the queued actions are automatically synchronized with your backend. This creates a seamless user experience regardless of network availability.
Why Use Offline Support?
- Better User Experience – Users can continue using the app even without internet.
- Data Integrity – Changes are stored locally and synced later, preventing data loss.
- Performance – Reduces unnecessary network calls by serving cached data first.
- Reliability – Handles network interruptions gracefully.
- Offline‑First Architecture – Builds apps that work everywhere, even in low‑connectivity areas.
Setting Up Hydrated Bloc
hydrated_bloc is an extension of flutter_bloc that automatically persists your state to disk. Add the required dependencies:
Initialize HydratedBloc before running the app. You need to provide a storage directory, usually from path_provider.
Making a Bloc Hydrated
To make a BLoC persist its state, extend HydratedBloc instead of Bloc and override fromJson and toJson to serialize your state.
Handling Complex State
For more complex states, make sure all fields are serializable. Use equatable to simplify comparisons and serialization.
Offline Queue Pattern
State persistence handles read operations. For mutations (POST, PUT, DELETE), you need a queue that stores pending operations when offline and replays them when online. Below is a simple queue implementation using GetStorage (or any persistent storage).
Syncing the Queue
Use a sync service that processes the queue when connectivity returns. It can be triggered by a connectivity listener.
In your BLoC, check connectivity before performing a mutation. If offline, queue the operation and update the state optimistically.
Conflict Resolution
When syncing, conflicts may arise (e.g., an item was deleted remotely but edited offline). Common strategies include:
- Last Write Wins – Compare timestamps and keep the latest version.
- Manual Merge – Show a conflict resolution UI for the user to decide.
- Accept Server State – Overwrite local changes with the server version, then reapply queued operations if possible.
- Version Vectors – Use vector clocks to track changes across multiple devices.
Best Practices
- Use
HydratedBlocfor UI state – Keep large datasets in a separate local database. - Separate queue from BLoC – Offline queue management belongs in a dedicated service.
- Implement optimistic updates – Update the UI immediately when offline, then sync later.
- Include timestamps – Helps with ordering and conflict resolution.
- Test offline scenarios – Simulate network changes using
flutter_offlineor connectivity mocks. - Limit queue size – Prevent unbounded growth by setting a maximum number of pending operations.
Common Mistakes
- ❌ Storing large data in hydrated_bloc – Performance issues. ✅ Use SQLite/Hive for large collections; keep only UI state in hydrated_bloc.
- ❌ Not handling sync errors – Failed operations get stuck. ✅ Implement retry logic with exponential backoff.
- ❌ Forgetting to update state after sync – UI may become inconsistent. ✅ After successful sync, refresh the state from the server or re‑fetch data.
- ❌ Missing
HydratedBlocinitialization – Causes runtime errors. ✅ Always setHydratedBloc.storagebeforerunApp. - ❌ Ignoring race conditions during sync – Concurrent syncs can cause duplicates. ✅ Use a flag to prevent multiple syncs running simultaneously.
Conclusion
Offline support in BLoC apps is achievable by combining hydrated_bloc for state persistence with a custom queue for pending mutations. This approach gives users a seamless experience even without connectivity, and automatically syncs when the network returns. With careful conflict handling, you can build robust offline-first Flutter applications.