Flutter本地数据库管理插件in_app_database的使用

发布于 1周前 作者 nodeper 来自 Flutter

Flutter本地数据库管理插件in_app_database的使用

初始化

在使用InAppDatabase之前,我们需要进行初始化。以下是一个简单的初始化示例:

final _kLimitations = {
  "users": const InAppWriteLimitation(5),
  "posts": const InAppWriteLimitation(10),
  "users/user_id/posts": const InAppWriteLimitation(10),
};

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final db = await SharedPreferences.getInstance();
  // Map<String, dynamic> db = {};
  InAppDatabase.init(
    limiter: (key) async {
      return _kLimitations[key]; // 可选参数
    },
    reader: (String key) async {
      return db.getString(key);
      // final x = db[key];
      // return x;
    },
    writer: (String key, String? value) async {
      if (value != null) {
        return db.setString(key, value);
        // db[key] = value;
        // return true;
      } else {
        return db.remove(key);
        // db.remove(key);
        // return true;
      }
    },
  );
  runApp(const MyApp());
}

使用场景

添加集合文档

添加一个新的用户到集合中:

Future<InAppDocumentSnapshot?> addCollectionDocument() {
  return InAppDatabase.i.collection("users").add({
    "username": UserFaker.username,
    "email": UserFaker.email,
    "age": UserFaker.age,
    "country": UserFaker.country,
    "photoUrl": UserFaker.photoUrl,
  });
}

设置新文档

设置一个特定的文档:

Future<InAppDocumentSnapshot?> setDocument() {
  return InAppDatabase.i.collection("users").doc("1").set({
    "username": "This is a username",
    "email": "This is a user email",
    "age": 24,
    "country": "Bangladesh",
    "photoUrl": "null",
    "hobbies": ['coding', 'gaming', 'sleeping'],
    "skills": ['flutter', 'android', 'node.js', 'spring boot', 'etc'],
  });
}

更新特定文档

更新特定用户的文档:

Future<InAppDocumentSnapshot?> updateSpecificDocument() {
  return InAppDatabase.i.collection("users").doc("1").update({
    'username': "This is a updated username",
    'email': "This is a updated user email",
    'age': InAppFieldValue.increment(2),
    'balance': InAppFieldValue.increment(-10.2),
    'hobbies': InAppFieldValue.arrayUnion(['swimming']),
    'skills': InAppFieldValue.arrayRemove(['node.js', 'spring boot']),
    'timestamp': InAppFieldValue.serverTimestamp(),
    'photoUrl': InAppFieldValue.delete(),
  });
}

删除特定文档

删除特定用户的文档:

Future<bool> deleteSpecificDocument() {
  return InAppDatabase.i.collection("users").doc("1").delete();
}

获取特定文档

获取特定用户的文档:

Future<InAppDocumentSnapshot?> getSpecificDocument() {
  return InAppDatabase.i.collection("users").doc("1").get();
}

获取所有文档

获取集合中的所有文档:

Future<InAppQuerySnapshot> getAllDocuments() {
  return InAppDatabase.i.collection("users").get();
}

获取特定文档(简单查询)

通过用户名获取特定用户的文档:

Future<InAppQuerySnapshot> getSpecificDocumentsByQuery() {
  return InAppDatabase.i
      .collection("users")
      .where("username", isEqualTo: "emma_smith")
      .get();
}

获取特定文档(复杂查询)

通过多个条件获取特定用户的文档:

Future<InAppQuerySnapshot> getSpecificDocumentsByQuery() {
  return InAppDatabase.i
      .collection("users")
      .where(InAppFilter.or([
        InAppFilter("username", isEqualTo: "emma_smith"),
        InAppFilter("age", isGreaterThanOrEqualTo: 50),
      ]))
      .where("age", isLessThanOrEqualTo: 60)
      .orderBy("age", descending: false)
      .orderBy("email", descending: false)
      .limit(10)
      .get();
}

获取所有文档(流)

通过流获取集合中的所有文档:

Stream<InAppQuerySnapshot> getCollectionSnapshots() {
  return InAppDatabase.i.collection("users").snapshots();
}

获取特定文档(简单查询)(流)

通过流获取特定用户的文档:

Stream<InAppQuerySnapshot> getSpecificDocumentsByQuerySnapshots() {
  return InAppDatabase.i
      .collection("users")
      .where("username", isEqualTo: "emma_smith")
      .snapshots();
}

获取特定文档(复杂查询)(流)

通过流获取特定用户的文档:

Stream<InAppQuerySnapshot> getComplexQuerySnapshots() {
  return InAppDatabase.i
      .collection("users")
      .where(InAppFilter.or([
        InAppFilter("username", isEqualTo: "emma_smith"),
        InAppFilter("age", isGreaterThanOrEqualTo: 50),
      ]))
      .where("age", isLessThanOrEqualTo: 60)
      .orderBy("age", descending: false)
      .orderBy("email", descending: false)
      .limit(10)
      .snapshots();
}

完整示例代码

以下是完整的示例代码,展示了如何使用InAppDatabase插件:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:in_app_database/in_app_database.dart';
import 'package:in_app_faker/in_app_faker.dart';
import 'package:shared_preferences/shared_preferences.dart';

final _kLimitations = {
  "users": const InAppWriteLimitation(5),
  "posts": const InAppWriteLimitation(10),
  "users/user_id/posts": const InAppWriteLimitation(10),
};

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final db = await SharedPreferences.getInstance();
  // Map<String, dynamic> db = {};
  InAppDatabase.init(
    limiter: (key) async {
      return _kLimitations[key]; // 可选参数
    },
    reader: (String key) async {
      return db.getString(key);
      // return db[key];
    },
    writer: (String key, String? value) async {
      if (value != null) {
        return db.setString(key, value);
        // db[key] = value;
        // return true;
      } else {
        return db.remove(key);
        // db.remove(key);
        // return true;
      }
    },
  );
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'In App Database',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({super.key});

  [@override](/user/override)
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("In App Database"),
        centerTitle: true,
      ),
      body: SafeArea(
        child: SizedBox(
          width: double.infinity,
          child: SingleChildScrollView(
            padding: const EdgeInsets.all(24),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                const Text(
                  "Counter Snapshot",
                  style: TextStyle(
                    color: Colors.black,
                    fontWeight: FontWeight.bold,
                    fontSize: 16,
                  ),
                ),
                StreamBuilder(
                  stream: InAppDatabase.i.collection("users").count().snapshots(),
                  builder: (context, s) {
                    final count = s.data?.count ?? 0;
                    return Text("Total users: $count");
                  },
                ),
                const SizedBox(height: 24),
                const Text(
                  "Document Snapshot",
                  style: TextStyle(
                    color: Colors.black,
                    fontWeight: FontWeight.bold,
                    fontSize: 16,
                  ),
                ),
                StreamBuilder(
                  stream: InAppDatabase.i.collection("users").doc("1").snapshots(),
                  builder: (context, s) {
                    final item = s.data?.data ?? {};
                    return ListTile(
                      leading: CircleAvatar(
                        child: Text("${item["age"]}"),
                      ),
                      title: Text("${item["username"]}"),
                      subtitle: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text("${item["email"]}"),
                          Text(
                            "Updated At: ${item["updateAt"] ?? "Not update yet"}",
                            maxLines: 1,
                          ),
                        ],
                      ),
                    );
                  },
                ),
                const SizedBox(height: 24),
                const Text(
                  "Collection Snapshots",
                  style: TextStyle(
                    color: Colors.black,
                    fontWeight: FontWeight.bold,
                    fontSize: 16,
                  ),
                ),
                StreamBuilder(
                  stream: InAppDatabase.i.collection("users").snapshots(),
                  builder: (context, s) {
                    final data = s.data?.docs ?? [];
                    return ListView.builder(
                      shrinkWrap: true,
                      physics: const NeverScrollableScrollPhysics(),
                      itemCount: data.length,
                      itemBuilder: (context, index) {
                        final item = data.elementAt(index).data;
                        return ListTile(
                          leading: CircleAvatar(
                            child: Text("${item?["age"]}"),
                          ),
                          title: Text("${item?["username"]}"),
                          subtitle: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text("${item?["email"]}"),
                              Text(
                                "Updated At: ${item?["updateAt"] ?? "Not update yet"}",
                                maxLines: 1,
                              ),
                            ],
                          ),
                        );
                      },
                    );
                  },
                ),
              ],
            ),
          ),
        ),
      ),
      floatingActionButton: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          Button(
            text: "Add",
            onClick: () => InAppDatabase.i.collection("users").add({
              "username": UserFaker.username,
              "email": UserFaker.email,
              "age": UserFaker.age,
              "country": UserFaker.country,
              "photoUrl": UserFaker.photoUrl,
            }),
          ),
          Button(
            text: "Set",
            onClick: () {
              InAppDatabase.i.collection("users").doc("1").set({
                "username": UserFaker.username,
                "email": UserFaker.email,
                "age": UserFaker.age,
                "country": UserFaker.country,
                "photoUrl": UserFaker.photoUrl,
              });
            },
          ),
          Button(
            text: "Update",
            onClick: () {
              InAppDatabase.i.collection("users").doc("1").update({
                "updateAt": DateTime.now().millisecondsSinceEpoch.toString(),
              });
            },
          ),
          Button(
            text: "Delete",
            onClick: () {
              InAppDatabase.i.collection("users").doc("1").delete();
            },
          ),
          Button(
            text: "Get",
            onClick: () {
              InAppDatabase.i.collection("users").doc("1").get().then((value) {
                DataBottomSheet.show(
                  context,
                  title: "Get",
                  contents: [value],
                );
              });
            },
          ),
          Button(
            text: "Gets",
            onClick: () {
              InAppDatabase.i.collection("users").get().then((value) {
                if (value.exists) {
                  DataBottomSheet.show(
                    context,
                    title: "Gets",
                    contents: value.docs,
                  );
                }
              });
            },
          ),
          Button(
            text: "Query",
            onClick: () {
              InAppDatabase.i
                  .collection("users")
                  .where("username", isEqualTo: "emma_smith")
                  .get()
                  .then((value) {
                if (value.exists) {
                  DataBottomSheet.show(
                    context,
                    title: "Query",
                    contents: value.docs,
                  );
                }
              });
            },
          ),
          Button(
            text: "Filter",
            onClick: () {
              InAppDatabase.i
                  .collection("users")
                  .where(InAppFilter.or([
                    InAppFilter("username", isEqualTo: "emma_smith"),
                    InAppFilter("age", isGreaterThanOrEqualTo: 50),
                  ]))
                  .where("age", isLessThanOrEqualTo: 60)
                  .orderBy("age", descending: false)
                  .orderBy("email", descending: false)
                  .limit(10)
                  .get()
                  .then((value) {
                if (value.exists) {
                  DataBottomSheet.show(
                    context,
                    title: "Filter",
                    contents: value.docs,
                  );
                }
              });
            },
          ),
        ],
      ),
    );
  }
}

class Button extends StatelessWidget {
  final String text;
  final VoidCallback onClick;

  const Button({
    super.key,
    required this.text,
    required this.onClick,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    final primary = Theme.of(context).primaryColor;
    return ElevatedButton(
      style: ElevatedButton.styleFrom(backgroundColor: primary),
      onPressed: onClick,
      child: Text(text, style: const TextStyle(color: Colors.white)),
    );
  }
}

class DataBottomSheet extends StatefulWidget {
  final String title;
  final List<InAppDocumentSnapshot> contents;

  const DataBottomSheet({
    super.key,
    required this.title,
    required this.contents,
  });

  [@override](/user/override)
  State<DataBottomSheet> createState() => _DataBottomSheetState();

  static Future<T?> show<T>(
    BuildContext context, {
    required String title,
    required List<InAppDocumentSnapshot> contents,
  }) {
    return showModalBottomSheet(
      context: context,
      builder: (context) {
        return DataBottomSheet(title: title, contents: contents);
      },
    );
  }
}

class _DataBottomSheetState extends State<DataBottomSheet> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 600,
      child: Column(
        children: [
          Container(
            width: 50,
            height: 8,
            margin: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.grey.withAlpha(50),
              borderRadius: BorderRadius.circular(25),
            ),
          ),
          Text(
            widget.title,
            style: const TextStyle(
              color: Colors.black,
              fontWeight: FontWeight.bold,
              fontSize: 16,
            ),
          ),
          const SizedBox(height: 16),
          Expanded(
            child: ListView.builder(
              itemCount: widget.contents.length,
              itemBuilder: (context, index) {
                final item = widget.contents.elementAtOrNull(index)?.data;
                return ListTile(
                  leading: CircleAvatar(
                    child: Text("${item?["age"]}"),
                  ),
                  title: Text("${item?["username"]}"),
                  subtitle: Text("${item?["email"]}"),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter本地数据库管理插件in_app_database的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter本地数据库管理插件in_app_database的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter本地数据库管理插件in_app_database的代码示例。这个示例将展示如何初始化数据库、创建表、插入数据、查询数据以及更新数据。

首先,确保你已经在pubspec.yaml文件中添加了in_app_database依赖:

dependencies:
  flutter:
    sdk: flutter
  in_app_database: ^x.y.z  # 请将x.y.z替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来是完整的代码示例:

import 'package:flutter/material.dart';
import 'package:in_app_database/in_app_database.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('In-App Database Example'),
        ),
        body: DatabaseExample(),
      ),
    );
  }
}

class DatabaseExample extends StatefulWidget {
  @override
  _DatabaseExampleState createState() => _DatabaseExampleState();
}

class _DatabaseExampleState extends State<DatabaseExample> {
  late InAppDatabase _db;

  @override
  void initState() {
    super.initState();
    initDatabase();
  }

  Future<void> initDatabase() async {
    _db = await InAppDatabase.openDatabase(
      version: 1,
      onCreate: (Database db, int version) async {
        await db.execute(
          'CREATE TABLE user ('
          'id INTEGER PRIMARY KEY AUTOINCREMENT,'
          'name TEXT NOT NULL,'
          'age INTEGER NOT NULL'
          ')',
        );
      },
      onUpgrade: (Database db, int oldVersion, int newVersion) async {
        await db.execute('DROP TABLE IF EXISTS user');
        onCreate(db, newVersion);
      },
    );
  }

  Future<void> insertUser(String name, int age) async {
    await _db.insert(
      'user',
      {'name': name, 'age': age},
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  Future<List<Map<String, Object>>> queryUsers() async {
    return await _db.query('user');
  }

  Future<void> updateUser(int id, String newName, int newAge) async {
    await _db.update(
      'user',
      {'name': newName, 'age': newAge},
      where: 'id = ?',
      whereArgs: [id],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          ElevatedButton(
            onPressed: () async {
              await insertUser('Alice', 30);
              setState(() {}); // 触发UI更新(如果有UI显示数据)
            },
            child: Text('Insert User'),
          ),
          SizedBox(height: 16),
          ElevatedButton(
            onPressed: () async {
              List<Map<String, Object>> users = await queryUsers();
              print('Users: $users');
              // 可以在这里更新UI来显示用户列表
            },
            child: Text('Query Users'),
          ),
          SizedBox(height: 16),
          ElevatedButton(
            onPressed: () async {
              await updateUser(1, 'Bob', 35);
              setState(() {}); // 触发UI更新(如果有UI显示数据)
            },
            child: Text('Update User'),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _db.close();
    super.dispose();
  }
}

解释

  1. 依赖管理:在pubspec.yaml中添加in_app_database依赖。
  2. 初始化数据库:在initDatabase方法中,使用InAppDatabase.openDatabase初始化数据库,并定义onCreateonUpgrade方法来创建表和升级数据库结构。
  3. 插入数据insertUser方法使用_db.insert将数据插入到user表中。
  4. 查询数据queryUsers方法使用_db.queryuser表中查询所有数据。
  5. 更新数据updateUser方法使用_db.update更新指定ID的用户信息。
  6. UI交互:使用ElevatedButton创建按钮,并在按钮点击事件中调用数据库操作方法。

请注意,这个示例中没有实现实际的UI更新来显示数据库中的数据,你可以根据需要在queryUsers方法调用后更新UI组件来显示用户列表。

回到顶部