Flutter数据库注解插件room_annotation的使用

Flutter数据库注解插件room_annotation的使用

在本教程中,我们将学习如何使用room_annotation插件来简化与sqflite数据库的交互。该插件通过注解自动生成数据库操作代码,从而减少手动编写CRUD(创建、读取、更新、删除)代码的工作量。

开始

首先,在您的pubspec.yaml文件中添加必要的依赖项:

dependencies:
  room_annotation: ^0.2.0
  sqflite: ^2.4.1
  json_annotation: ^4.9.0

dev_dependencies:
  room_generator: ^0.2.0
  build_runner: ^2.4.14
  json_serializable: ^6.9.2

运行flutter pub get以安装这些依赖项。

创建实体类

接下来,创建您的数据模型类。这里我们定义一个Company类,它包含一些基本属性并使用注解来自动生成数据库表结构。

import 'package:json_annotation/json_annotation.dart';
import 'package:room_annotation/room_annotation.dart';

part 'company.g.dart';

[@Entity](/user/Entity)()
[@JsonSerializable](/user/JsonSerializable)()
class Company {
  [@PrimaryKey](/user/PrimaryKey)()
  final String document;

  [@Column](/user/Column)()
  String? name;

  [@Column](/user/Column)(since: 2)
  String? phone;

  Company({
    required this.document,
    this.name,
    this.phone,
  });

  factory Company.fromJson(Map<String, dynamic> json) => _$CompanyFromJson(json);

  Map<String, dynamic> toJson() => _$CompanyToJson(this);
}

创建数据库

现在,创建一个数据库类来管理数据库版本和实体类。

import 'package:room_annotation/room_annotation.dart';
import 'package:sqflite/sqflite.dart';

import 'company.dart';

part 'database.g.dart';

[@RoomDatabase](/user/RoomDatabase)(
  version: 2,
  entities: [Company],
)
class MyDatabase with _$MyDatabase {}

创建CRUD仓库

接下来,创建一个仓库类来处理具体的CRUD操作。

import 'package:room_annotation/room_annotation.dart';
import 'package:sqflite/sqflite.dart';

import 'database.dart';
import 'company.dart';

part 'company_repository.g.dart';

[@CrudRepository](/user/CrudRepository)(
  database: MyDatabase,
  entity: Company,
)
class CompanyRepository with _$CompanyRepository {}

运行和测试

最后,让我们编写一些代码来测试我们的数据库操作。

import 'company.dart';
import 'company_repository.dart';
import 'database.dart';

void main() async {
  final db = MyDatabase();
  await db.initialize();
  final repository = CompanyRepository();
  await repository.save(
    Company(
      document: '123456',
      name: 'The Company',
    ),
  );
  final companies = await repository.findAll();
  for (final company in companies) {
    print(company.name);
  }
}

完整示例

以下是一个完整的示例,展示了如何将上述所有部分组合在一起,并在Flutter应用中展示数据列表。

import 'dart:math';

import 'package:flutter/material.dart' hide Column;
import 'package:json_annotation/json_annotation.dart';
import 'package:room_annotation/room_annotation.dart';
import 'package:sqflite/sqflite.dart';

part 'main.g.dart';

void main() => runApp(const MyApp());

[@RoomDatabase](/user/RoomDatabase)(
  version: 5,
  entities: [Company],
)
class MyDatabase with _$MyDatabase {}

[@CrudRepository](/user/CrudRepository)(
  database: MyDatabase,
  entity: Company,
)
class CompanyRepository with _$CompanyRepository {}

[@Entity](/user/Entity)()
[@JsonSerializable](/user/JsonSerializable)()
class Company {
  [@PrimaryKey](/user/PrimaryKey)()
  final String document;

  [@Column](/user/Column)()
  String? name;

  [@Column](/user/Column)(since: 2)
  String? phone;

  [@Column](/user/Column)(since: 3)
  String? address;

  [@Column](/user/Column)(since: 4)
  String? metadata;

  [@Column](/user/Column)(since: 5)
  String? metadata2;

  [@Column](/user/Column)(since: 5)
  String? metadata3;

  Company({
    required this.document,
    this.name,
    this.phone,
    this.address,
    this.metadata,
    this.metadata2,
    this.metadata3,
  });

  factory Company.fromJson(Map<String, dynamic> json) => _$CompanyFromJson(json);

  Map<String, dynamic> toJson() => _$CompanyToJson(this);
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

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

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late MyDatabase database;
  final companyRepository = CompanyRepository();
  bool isLoading = true;

  [@override](/user/override)
  void initState() {
    super.initState();
    initializeDatabase();
  }

  Future<void> initializeDatabase() async {
    final database = MyDatabase();
    await database.initialize();
    this.database = database;
    if (mounted) {
      setState(() => isLoading = false);
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: isLoading
          ? null
          : FutureBuilder(
              future: companyRepository.findAll(),
              builder: (context, snapshot) {
                final companies = snapshot.data ?? [];
                return ListView.builder(
                  itemCount: companies.length,
                  itemBuilder: (context, index) {
                    final company = companies[index];
                    return ListTile(
                      title: Text(company.metadata ?? 'empty'),
                      leading: IconButton(
                        onPressed: () {},
                        icon: IconButton(
                          onPressed: () async {
                            await showDialog(
                              context: context,
                              builder: (context) {
                                final controller = TextEditingController();
                                return AlertDialog(
                                  content: TextFormField(
                                    controller: controller,
                                    decoration: InputDecoration(
                                      border: OutlineInputBorder(),
                                      hintText: 'name',
                                    ),
                                  ),
                                  actions: [
                                    TextButton(
                                      onPressed: () {
                                        company.name = controller.text.trim();
                                        Navigator.pop(context);
                                      },
                                      child: Text('save'),
                                    ),
                                  ],
                                );
                              },
                            );
                            setState(() => isLoading = true);
                            await companyRepository.save(company);
                            if (mounted) setState(() => isLoading = false);
                          },
                          icon: Icon(Icons.edit),
                        ),
                      ),
                      trailing: IconButton(
                        onPressed: () async {
                          setState(() => isLoading = true);
                          await companyRepository.deleteById(company.document);
                          if (mounted) setState(() => isLoading = false);
                        },
                        icon: Icon(Icons.delete),
                      ),
                    );
                  },
                );
              },
            ),
      floatingActionButton: isLoading
          ? null
          : FloatingActionButton(
              onPressed: () async {
                setState(() => isLoading = true);
                await companyRepository.save(
                  Company(
                    name: 'hello',
                    document: Random().nextInt(1000).toString(),
                    metadata: Random().nextInt(1000).toString(),
                  ),
                );
                if (mounted) setState(() => isLoading = false);
              },
            ),
    );
  }
}

更多关于Flutter数据库注解插件room_annotation的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


在Flutter中,room_annotation 并不是原生支持的插件,因为 room_annotation 是专门用于 Android Jetpack Room 持久化库的注解集合。然而,Flutter 社区中有一些插件可以实现类似的功能,比如 floor,它是一个受 Room 启发的轻量级 SQLite ORM(对象关系映射)库。

下面是一个使用 floor 插件的示例,它模仿了 Room 的注解和功能。

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 floor 依赖:

dependencies:
  flutter:
    sdk: flutter
  floor: ^1.0.0 # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 创建数据模型

使用 @Entity 注解来标记你的数据模型。例如,创建一个 User 类:

import 'package:floor/floor.dart';

@Entity(tableName: 'users')
class User {
  @PrimaryKey(autoGenerate: true)
  final int id;

  @ColumnInfo(name: 'name')
  final String name;

  User({required this.name});
}

3. 创建 DAO 接口

DAO(数据访问对象)用于定义数据库操作。使用 @Dao 注解来标记你的 DAO 接口,并定义所需的方法。例如:

import 'package:floor/floor.dart';
import 'user.dart';

@Dao
abstract class UserDao {
  @Insert(onConflict: OnConflictStrategy.replace)
  Future<void> insertUser(User user);

  @Query('SELECT * FROM users')
  Future<List<User>> getAllUsers();

  @Update
  Future<void> updateUser(User user);

  @Delete
  Future<void> deleteUser(User user);
}

4. 定义数据库

使用 @Database 注解来标记你的数据库类,并指定 DAO 接口和数据模型。例如:

import 'package:floor/floor.dart';
import 'user.dart';
import 'user_dao.dart';

@Database(version: 1, entities: [User], daos: [UserDao])
abstract class AppDatabase extends FloorDatabase {
  UserDao get userDao;
}

5. 打开数据库连接

在你的 Flutter 应用中打开数据库连接。通常在应用启动时进行此操作。例如,在 main.dart 中:

import 'package:flutter/material.dart';
import 'package:floor/floor.dart';
import 'app_database.dart';
import 'user.dart';
import 'user_dao.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final database = await $FloorAppDatabase.databaseBuilder('my_database.db').build();
  runApp(MyApp(database.userDao));
}

class MyApp extends StatelessWidget {
  final UserDao userDao;

  MyApp(this.userDao);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Floor Demo')),
        body: Center(
          child: FutureBuilder<List<User>>(
            future: userDao.getAllUsers(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                final users = snapshot.data ?? [];
                return Text('Users: ${users.length}');
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () async {
            await userDao.insertUser(User(name: 'John Doe'));
          },
          tooltip: 'Add User',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

6. 生成 Floor 数据库文件

由于 Floor 使用代码生成来简化数据库操作,你需要添加一个构建脚本来生成这些文件。在 build.yaml 文件中添加以下内容:

targets:
  $default:
    builders:
      floor_generator:
        enabled: true

然后运行 flutter pub run build_runner build 来生成所需的 Floor 文件。

总结

以上示例展示了如何在 Flutter 应用中使用 floor 插件来实现类似 Android Room 的数据库注解和功能。通过定义数据模型、DAO 接口和数据库类,你可以轻松地在 Flutter 中进行数据库操作。

回到顶部