Adopting PowerSync can simplify the architecture of your app by using a local SQLite database as the single source of truth for all data.
For a general discussion on how PowerSync fits into modern app architecture on Flutter, also see this blogpost.
Future
and Stream
classes from dart:async
. Given how widely used these are
in the Dart ecosystem, PowerSync works well with all popular approaches for state management, such as:
- Providers with
package:provider
: Create your database as aProvider
and expose watched queries to child widgets withStreamProvider
! The provider for databases shouldclose()
the database indispose
. - Providers with
package:riverpod
: We mention relevant snippets below. - Dependency injection with
package:get_it
: PowerSync databases can be registered withregisterSingletonAsync
. Again, make sure toclose()
the database in thedispose
callback. - The BLoC pattern with the
bloc
package: You can easily listen to watched queries in Cubits (although, if you find your Blocs and Cubits becoming trivial wrappers around database streams, consider justwatch()
ing database queries in widgets directly. That doesn’t make your app less testable!). To simplify state management, avoid the use of hydrated blocs and cubits for state that depends on database queries. With PowerSync, regular data is already available locally and doesn’t need a second local cache.
Riverpod
We have a complete example on using PowerSync
with modern Flutter libraries like Riverpod, Drift and
auto_route
.connect
and
disconnect
calls there, for instance by listening to the authentication state:
Running queries
To expose auto-updating query results, use aStreamProvider
reading the database:
Waiting for sync
If you were awaitingwaitForFirstSync
before, you can keep doing that: