Data & Repository
Managing offline data flow with FluxyRepository.
Data & Repository
The FluxRepository is a foundational abstraction in Fluxy designed for building robust, offline-first applications. It connects your UI to remote data sources (like REST APIs or Databases) while synchronizing with local storage (like SQLite or Shared Preferences).
FluxRepository
A FluxRepository is essentially a FluxController enhanced with data management capabilities:
- Offline Sync Logic: Built-in support for "Local First, Then Remote" synchronization.
- Stream Binding: Automatic lifecycle management for database streams (e.g., Firebase, realm).
- Data Guard Integration: Uses
FluxyDataGuardfor retries and resilience.
Creating a Repository
Extend FluxRepository and implement the sync() usage or bind streams directly.
class UserRepository extends FluxRepository {
// Define Reactive State
final user = flux<User?>(null);
@override
void onInit() {
// Automatically load data when repo starts
loadUser();
}
Future<void> loadUser() async {
// Use DataGuard for SWR (Stale-While-Revalidate)
await FluxyDataGuard.swr(
local: _fetchLocalUser(),
remote: _fetchRemoteUser(),
onData: (data) => user.value = data,
);
}
Future<User?> _fetchLocalUser() async {
// Fetch from Hive/SQLite
}
Future<User> _fetchRemoteUser() async {
// Fetch from API
return await Fx.http.get('/me');
}
}Stream Subscriptions
If you work with real-time databases (like Firebase), manual subscription management is error-prone. FluxRepository simplifies this with bindStream.
class ChatRepository extends FluxRepository {
final messages = flux<List<Message>>([]);
void listenToChat(String chatId) {
// This subscription is automatically canceled when
// the repository is disposed. No memory leaks!
bindStream(
MyDatabase.chatStream(chatId),
messages
);
}
}Every FluxRepository comes with a built-in isOnline signal. This is automatically synchronized with the global connectivity engine, allowing you to build resilient, offline-ready logic with zero configuration.
Use Case: Automated Synchronization
A common requirement is to "Queue" data while offline and "Flush" it once the connection returns.
class TaskRepository extends FluxRepository {
final tasks = fluxList<Task>([], persistKey: 'offline_tasks');
@override
void onInit() {
super.onInit();
// Automatically trigger a sync whenever the device joins a network
fluxEffect(() {
if (isOnline.value && tasks.isNotEmpty) {
_uploadPendingTasks();
}
});
}
Future<void> _uploadPendingTasks() async {
Fx.toast.info("Connection Restored. Syncing ${tasks.length} items...");
for (var task in tasks) {
final success = await Fx.http.post('/tasks', body: task.toJson());
if (success) tasks.remove(task);
}
}
}Data Layer vs Service Layer
It is easy to confuse a FluxRepository with a Service. In Fluxy, they have distinct roles:
- Repository (The Manager): Manages Business Models and feature-specific data (e.g.,
UserRepository,PaymentRepository). - Service (The Tool): Provides Generic Capabilities used across the app (e.g.,
logger_service.dart,api_service.dart).
Rule: If your logic involves fetching "Products" or "Orders," it belongs in a Repository. If your logic involves "Sending an Analytics Event" or "Opening the Camera," it belongs in a Service.