Flutter离线优先数据同步插件brick_offline_first_with_supabase的使用
Flutter离线优先数据同步插件 brick_offline_first_with_supabase
的使用
brick_offline_first_with_supabase
是一个用于Flutter应用的离线优先数据同步插件,它简化了Supabase与OfflineFirstRepository
的集成。本文将详细介绍如何使用该插件,并提供完整的示例代码。
Repository
配置仓库
首先,我们需要配置一个继承自OfflineFirstWithSupabaseRepository
的仓库类。以下是一个示例:
import 'package:brick_offline_first_with_supabase/brick_offline_first_with_supabase.dart';
import 'package:brick_sqlite/brick_sqlite.dart';
import 'package:brick_sqlite/memory_cache_provider.dart';
import 'package:brick_supabase/brick_supabase.dart';
import 'package:sqflite/sqflite.dart' show databaseFactory;
import 'package:supabase/supabase.dart';
// 假设已经生成了 brick.g.dart 和 schema.g.dart 文件
import 'brick/brick.g.dart';
import 'brick/db/schema.g.dart';
class MyRepository extends OfflineFirstWithSupabaseRepository {
static late MyRepository? _singleton;
MyRepository._({
required super.supabaseProvider,
required super.sqliteProvider,
required super.migrations,
required super.offlineRequestQueue,
super.memoryCacheProvider,
});
factory MyRepository() => _singleton!;
static void configure({
required String supabaseUrl,
required String supabaseAnonKey,
}) {
// 创建客户端和队列
final (client, queue) = OfflineFirstWithSupabaseRepository.clientQueue(
databaseFactory: databaseFactory,
);
// 配置 Supabase 客户端
final provider = SupabaseProvider(
SupabaseClient(supabaseUrl, supabaseAnonKey, httpClient: client),
modelDictionary: supabaseModelDictionary,
);
// 初始化仓库
_singleton = MyRepository._(
supabaseProvider: provider,
sqliteProvider: SqliteProvider(
'my_repository.sqlite',
databaseFactory: databaseFactory,
modelDictionary: sqliteModelDictionary,
),
migrations: migrations,
offlineRequestQueue: queue,
memoryCacheProvider: MemoryCacheProvider(),
);
}
}
使用 supabase_flutter
包
如果你使用的是 supabase_flutter
包,可以在初始化时创建客户端和队列:
final (client, queue) = OfflineFirstWithSupabaseRepository.clientQueue(databaseFactory: databaseFactory);
await Supabase.initialize(url: supabaseUrl, anonKey: supabaseAnonKey, httpClient: client);
final supabaseProvider = SupabaseProvider(Supabase.instance.client, modelDictionary: ...);
离线队列注意事项
在某些情况下,你可能需要忽略特定路径的请求。例如,Supabase的Auth或Storage路径默认不会被缓存和重试:
final (client, queue) = OfflineFirstWithSupabaseRepository.clientQueue(
databaseFactory: databaseFactory,
ignorePaths: {},
);
// 如果你不希望重试某些函数并处理响应,可以添加如下路径:
final (client, queue) = OfflineFirstWithSupabaseRepository.clientQueue(
databaseFactory: databaseFactory,
ignorePaths: {
'/auth/v1',
'/storage/v1',
'/functions/v1'
},
);
注意:如果更改了ignorePaths
的默认值,你需要维护这些路径以适应Supabase的更新。
实时数据同步
Brick支持通过Supabase实时事件自动更新数据。首先设置你的表来广播变更,然后在应用程序中监听这些变更:
// 监听所有变更
final customers = MyRepository().subscribeToRealtime<Customer>();
// 或者监听特定过滤条件的结果
final customers = MyRepository().subscribeToRealtime<Customer>(query: Query.where('id', 1));
// 使用流结果
final customersSubscription = customers.listen((value) {});
// 始终关闭你的流
await customersSubscription.cancel();
注意:实时数据同步可能会变得昂贵,请设计你的应用程序以适应适当的规模。对于更便宜的设备内反应性,可以使用.subscribe()
。
模型
@ConnectOfflineFirstWithSupabase
这个注解用于标记可以被一个或多个提供程序序列化的模型:
@ConnectOfflineFirstWithSupabase(
supabaseConfig: SupabaseSerializable(),
sqliteConfig: SqliteSerializable(),
)
class MyModel extends OfflineFirstWithSupabaseModel {}
关联和外键
字段类型为extends OfflineFirstWithSupabaseModel
的类会自动被视为Supabase中的外键。只有当列名与字段名不同时,才需要指定列名:
class User extends OfflineFirstWithSupabaseModel {
@Supabase(foreignKey: 'address_id')
final Address address;
@Sqlite(ignore: true)
String get addressId => address.id;
}
class Address extends OfflineFirstWithSupabaseModel{
final String id;
}
注意:如果关联是可空的(如Address?
),则查询可能会返回数据库中的所有记录。在这种情况下,你可以使用Supabase的策略来解决这个问题。
示例Demo
以下是一个完整的示例,展示了如何使用brick_offline_first_with_supabase
插件:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 配置仓库
MyRepository.configure(
supabaseUrl: 'YOUR_SUPABASE_URL',
supabaseAnonKey: 'YOUR_SUPABASE_ANON_KEY',
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
更多关于Flutter离线优先数据同步插件brick_offline_first_with_supabase的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter离线优先数据同步插件brick_offline_first_with_supabase的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个使用Flutter离线优先数据同步插件 brick_offline_first_with_supabase
的代码示例。这个插件允许你在Flutter应用中实现离线优先的数据同步,并且与Supabase进行集成。
首先,确保你已经在你的 pubspec.yaml
文件中添加了必要的依赖:
dependencies:
flutter:
sdk: flutter
brick_offline_first_with_supabase: ^latest_version # 请替换为最新版本号
supabase_flutter: ^latest_version # 请替换为最新版本号
然后,运行 flutter pub get
来获取这些依赖。
接下来,在你的 Flutter 应用中,你可以按照以下步骤来设置和使用 brick_offline_first_with_supabase
插件。
- 初始化 Supabase 客户端:
import 'package:supabase_flutter/supabase_flutter.dart';
final SupabaseClient supabase = SupabaseClient(
url: 'YOUR_SUPABASE_URL',
anonKey: 'YOUR_ANON_KEY',
);
- 配置
brick_offline_first_with_supabase
:
import 'package:brick_offline_first_with_supabase/brick_offline_first_with_supabase.dart';
// 配置离线优先数据库
final OfflineDatabase offlineDatabase = OfflineDatabase(
supabaseClient: supabase,
tableName: 'your_table_name', // 替换为你的表名
localStorage: LocalStorage(), // 使用默认的本地存储
);
- 创建数据模型:
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:json_annotation/json_annotation.dart';
part 'your_model.g.dart';
@freezed
class YourModel with _$YourModel {
const factory YourModel({
required String id,
required String name,
// 其他字段
}) = _YourModel;
factory YourModel.fromJson(Map<String, dynamic> json) => _$YourModelFromJson(json);
Map<String, dynamic> toJson() => _$YourModelToJson(this);
}
运行 flutter pub run build_runner build
来生成 your_model.g.dart
文件。
- 执行 CRUD 操作:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化离线数据库
await offlineDatabase.initialize();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Offline First Demo')),
body: OfflineDemo(),
),
);
}
}
class OfflineDemo extends StatefulWidget {
@override
_OfflineDemoState createState() => _OfflineDemoState();
}
class _OfflineDemoState extends State<OfflineDemo> {
late OfflineDatabaseClient<YourModel> dbClient;
@override
void initState() {
super.initState();
dbClient = offlineDatabase.createClient<YourModel>(
fromJson: (json) => YourModel.fromJson(json),
toJson: (model) => model.toJson(),
);
}
void addItem() async {
final newItem = YourModel(id: Uuid().v4(), name: 'New Item'); // 使用 Uuid 生成唯一ID
await dbClient.insert(newItem);
// 同步到Supabase(可选,根据需求在合适时机调用)
// await offlineDatabase.sync();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: addItem,
child: Text('Add Item'),
),
// 显示数据列表(示例)
Expanded(
child: FutureBuilder<List<YourModel>>(
future: dbClient.selectAll(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final items = snapshot.data ?? [];
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Text(items[index].name);
},
);
} else {
return CircularProgressIndicator();
}
},
),
),
],
),
);
}
}
在上面的代码中,我们展示了如何初始化 brick_offline_first_with_supabase
插件,创建数据模型,并执行基本的 CRUD 操作。你可以根据需要扩展和修改这些代码,以适应你的具体应用场景。
请注意,这只是一个基本的示例,实际项目中可能需要处理更多的错误情况、同步策略等。此外,确保在实际部署前替换 YOUR_SUPABASE_URL
和 YOUR_ANON_KEY
为你的 Supabase 项目的实际值。