跳到正文
cccskills
免费在 GitHub 公开

firebase-database

Use when syncing real-time data, structuring JSON trees, reading/writing, creating listeners, enabling offline persistence, managing presence, sharding, or writing security rules.

中文简介正在准备中。当前显示原文说明。

集成工具Firebase
查看安装方法

包含的文件(1)

  • SKILL.md7.8 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Firebase Realtime Database Skill

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.

When to Use

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.


1. Database Selection

Choose Realtime Database when the app needs:

  • Simple data models with simple lookups.
  • Extremely low-latency synchronization (typical response times under 10ms).
  • Deep queries that return an entire subtree by default.
  • Access to data at any granularity, down to individual leaf-node values.
  • Frequent state-syncing with built-in presence functionality.

Choose Cloud Firestore instead for rich data models requiring queryability, scalability, and high availability.


2. Setup and Configuration

flutter pub add firebase_database
import 'package:firebase_database/firebase_database.dart';

// After Firebase.initializeApp():
final DatabaseReference ref = FirebaseDatabase.instance.ref();
  • Select the database location closest to users.
  • Enable persistence for offline capabilities:
FirebaseDatabase.instance.setPersistenceEnabled(true);
FirebaseDatabase.instance.setPersistenceCacheSizeBytes(10000000); // 10MB

Setup Checklist

  1. Confirm Firebase.initializeApp() completes before accessing FirebaseDatabase.instance.
  2. Set persistence before any read/write operations.
  3. Verify connectivity by writing a test value and reading it back.

3. Data Structure

  • Structure data as a flattened JSON tree — avoid deep nesting.
  • Maximum nesting depth is 32 levels.
  • Design the data structure to support the most common queries.
  • Use push IDs for unique identifiers in list-type data:
final newPostKey = FirebaseDatabase.instance.ref().child('posts').push().key;
  • Denormalize data when necessary — Realtime Database does not support joins.
  • Custom keys must be UTF-8 encoded, max 768 bytes, and cannot contain . $ # [ ] / or ASCII control characters 0-31 or 127.

Flattened Structure Example

// 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.


4. Indexing and Querying

  • Queries can sort or filter on a property, but not both in the same query.
  • Use .indexOn in security rules to index frequently queried fields:
{
  "rules": {
    "dinosaurs": {
      ".indexOn": ["height", "length"]
    }
  }
}
  • Queries are deep by default and return the entire subtree.
  • Sort with orderByChild(), orderByKey(), or orderByValue():
final query = FirebaseDatabase.instance.ref("dinosaurs").orderByChild("height");
  • Limit results with limitToFirst() or limitToLast():
final query = ref.orderByChild("height").limitToFirst(10);
  • Range queries using startAt(), endAt(), and equalTo():
// Find users whose name starts with "A"
final query = ref.child("users")
    .orderByChild("name")
    .startAt("A")
    .endAt("A\uf8ff");

5. Read and Write Operations

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);
  • Keep individual write operations under 256KB.
  • Use listeners for real-time updates rather than polling.

6. Designing for Scale

  • Realtime Database scales to ~200,000 concurrent connections and 1,000 writes/second per database. For higher scale, shard data across multiple database instances.
  • Avoid storing large blobs — use Firebase Storage for files.
  • Use server timestamps for consistent time tracking:
await FirebaseDatabase.instance.ref('posts/123/timestamp').set(ServerValue.timestamp);
  • Implement fan-out patterns for data accessed from multiple paths.
  • Avoid deep nesting — it leads to performance issues when retrieving data.

7. Offline Capabilities and Presence

FirebaseDatabase.instance.setPersistenceEnabled(true);

// Keep critical paths synced when offline
FirebaseDatabase.instance.ref('important-data').keepSynced(true);

Connection State and Presence

// 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,
    });
  }
});
  • Use value events (onValue) to read data and get notified of updates — optimized for online/offline transitions.
  • Use 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.

8. Security

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}
  • Use .read, .write, .validate, and .indexOn to control access and validate data.
  • Read and write rules cascade in Realtime Database — a parent rule granting access cannot be revoked by a child rule.
  • Use the auth variable to authenticate users in security rules.

Data Validation Example

{
  "rules": {
    "messages": {
      "$messageId": {
        ".validate": "newData.hasChildren(['text', 'sender', 'timestamp'])",
        "text": {
          ".validate": "newData.isString() && newData.val().length <= 500"
        }
      }
    }
  }
}
  • Test rules thoroughly using the Firebase console's rules simulator.
  • Use the Firebase Emulator Suite for local testing.

References

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

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).

中文简介正在准备中。当前显示原文说明。

evanca/flutter-ai-rules6532026年10月10日 更新

Use when creating a feature, designing folder structure, adding repositories/services/view models, wiring dependency injection, or deciding which layer owns logic.

中文简介正在准备中。当前显示原文说明。

evanca/flutter-ai-rules6532026年10月10日 更新

bloc

免费

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.

中文简介正在准备中。当前显示原文说明。

evanca/flutter-ai-rules6532026年10月10日 更新

Use when asked to review a PR, MR, branch, or diff, audit changed files, or check code quality.

中文简介正在准备中。当前显示原文说明。

evanca/flutter-ai-rules6532026年10月10日 更新

Use when writing switch statements, refactoring if-else chains, creating data classes, choosing records vs classes, destructuring values, or modernizing pre-Dart-3 code.

中文简介正在准备中。当前显示原文说明。

evanca/flutter-ai-rules6532026年10月10日 更新

Use when building AI agents in Dart, implementing Genkit flows or tools, integrating LLMs into Dart or Flutter applications, or using Genkit Dart plugins.

中文简介正在准备中。当前显示原文说明。

evanca/flutter-ai-rules6532026年10月10日 更新

查看 evanca 的全部技能

报告此技能的问题