Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions, reduced motion, or target sizes; not language/culture/device (see inclusive-design).
中文简介正在准备中。当前显示原文说明。
Use when syncing real-time data, structuring JSON trees, reading/writing, creating listeners, enabling offline persistence, managing presence, sharding, or writing security rules.
中文简介正在准备中。当前显示原文说明。
安装前可以查看交给 AI 代理的指令内容。
This skill defines how to correctly implement Firebase Realtime Database in Flutter applications, covering data modeling, queries, real-time sync, offline support, and security rules.
Use this skill when working with Firebase Realtime Database for simple data models, low-latency sync, or presence functionality. For rich data models requiring complex queries and high scalability, use Cloud Firestore instead.
Choose Realtime Database when the app needs:
Choose Cloud Firestore instead for rich data models requiring queryability, scalability, and high availability.
flutter pub add firebase_database
import 'package:firebase_database/firebase_database.dart';
// After Firebase.initializeApp():
final DatabaseReference ref = FirebaseDatabase.instance.ref();
FirebaseDatabase.instance.setPersistenceEnabled(true);
FirebaseDatabase.instance.setPersistenceCacheSizeBytes(10000000); // 10MB
Firebase.initializeApp() completes before accessing FirebaseDatabase.instance.final newPostKey = FirebaseDatabase.instance.ref().child('posts').push().key;
. $ # [ ] / or ASCII control characters 0-31 or 127.// Instead of nesting chat messages inside rooms:
// rooms/roomId/messages/messageId/...
// Flatten into separate top-level paths:
// rooms/roomId: { name: "General", createdBy: "uid1" }
// room-members/roomId: { uid1: true, uid2: true }
// room-messages/roomId/messageId: { text: "Hello", sender: "uid1", timestamp: ... }
This pattern allows reading room metadata without downloading all messages.
.indexOn in security rules to index frequently queried fields:{
"rules": {
"dinosaurs": {
".indexOn": ["height", "length"]
}
}
}
orderByChild(), orderByKey(), or orderByValue():final query = FirebaseDatabase.instance.ref("dinosaurs").orderByChild("height");
limitToFirst() or limitToLast():final query = ref.orderByChild("height").limitToFirst(10);
startAt(), endAt(), and equalTo():// Find users whose name starts with "A"
final query = ref.child("users")
.orderByChild("name")
.startAt("A")
.endAt("A\uf8ff");
Read once:
final snapshot = await FirebaseDatabase.instance.ref('users/123').get();
if (snapshot.exists) {
print(snapshot.value);
}
Real-time listener:
final subscription = FirebaseDatabase.instance
.ref('users/123')
.onValue
.listen((event) {
final data = event.snapshot.value;
print(data);
});
// Cancel when no longer needed:
subscription.cancel();
A DatabaseEvent fires every time data changes at the reference, including changes to children.
Write (replace):
await ref.set({
"name": "John",
"age": 18,
"created_at": ServerValue.timestamp,
});
Update (partial):
await ref.update({"age": 19});
Atomic transaction:
final result = await FirebaseDatabase.instance
.ref('posts/123/likes')
.runTransaction((currentValue) {
return Transaction.success((currentValue as int? ?? 0) + 1);
});
print('Likes: ${result.snapshot.value}');
Multi-path atomic update:
final updates = <String, dynamic>{
'posts/$postId': postData,
'user-posts/$uid/$postId': postData,
};
await FirebaseDatabase.instance.ref().update(updates);
await FirebaseDatabase.instance.ref('posts/123/timestamp').set(ServerValue.timestamp);
FirebaseDatabase.instance.setPersistenceEnabled(true);
// Keep critical paths synced when offline
FirebaseDatabase.instance.ref('important-data').keepSynced(true);
// Detect connection state
FirebaseDatabase.instance.ref('.info/connected').onValue.listen((event) {
final connected = event.snapshot.value as bool? ?? false;
if (connected) {
// Set online status and configure onDisconnect cleanup
final presenceRef = FirebaseDatabase.instance.ref('status/${uid}');
presenceRef.set({'online': true, 'last_seen': ServerValue.timestamp});
presenceRef.onDisconnect().set({
'online': false,
'last_seen': ServerValue.timestamp,
});
}
});
onValue) to read data and get notified of updates — optimized for online/offline transitions.get() only when data is needed once; it probes local cache if the server is unavailable.onDisconnect() operations are executed server-side, ensuring cleanup even if the app crashes.{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
.read, .write, .validate, and .indexOn to control access and validate data.auth variable to authenticate users in security rules.{
"rules": {
"messages": {
"$messageId": {
".validate": "newData.hasChildren(['text', 'sender', 'timestamp'])",
"text": {
".validate": "newData.isString() && newData.val().length <= 500"
}
}
}
}
}
还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions, reduced motion, or target sizes; not language/culture/device (see inclusive-design).
中文简介正在准备中。当前显示原文说明。
Use when creating a feature, designing folder structure, adding repositories/services/view models, wiring dependency injection, or deciding which layer owns logic.
中文简介正在准备中。当前显示原文说明。
Use when creating a Cubit or Bloc, modeling state with sealed classes or status enums, wiring BlocBuilder/BlocListener/BlocProvider, writing bloc tests, or choosing between Cubit and Bloc.
中文简介正在准备中。当前显示原文说明。
Use when asked to review a PR, MR, branch, or diff, audit changed files, or check code quality.
中文简介正在准备中。当前显示原文说明。
Use when writing switch statements, refactoring if-else chains, creating data classes, choosing records vs classes, destructuring values, or modernizing pre-Dart-3 code.
中文简介正在准备中。当前显示原文说明。
Use when building AI agents in Dart, implementing Genkit flows or tools, integrating LLMs into Dart or Flutter applications, or using Genkit Dart plugins.
中文简介正在准备中。当前显示原文说明。