乐趣区

关于flutter:Strapi助力Flutter开发国际化App-使用Sqlite数据库

https://pub.dev/packages/floor

在 Flutter 我的项目中配置依赖库的援用pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  floor: ^1.2.0

dev_dependencies:
  floor_generator: ^1.2.0
  build_runner: ^2.1.2

创立实体与视图[project_root]/lib/app/data/entity/vegetalbe.dart

import 'package:floor/floor.dart';

@Entity(tableName: "vegetables")
class Vegetable {@PrimaryKey(autoGenerate: true)
  final int? id;

  final String name;

  final String locale;

  final String desc;

  @ColumnInfo(name: 'created_at')
  final int createTime;

  @ColumnInfo(name: 'updated_at')
  final int updateTime;

  Vegetable(
    this.id,
    this.name,
    this.locale,
    this.desc, {
    int? createTime,
    int? updateTime,
  })  : this.createTime = createTime ?? DateTime.now().millisecondsSinceEpoch,
        this.updateTime = updateTime ?? DateTime.now().millisecondsSinceEpoch;}

@DatabaseView(
    'SELECT    v.id,    v.name,    v.desc,    v.locale,    uf.hash,    uf.ext,     v.created_at,    v.updated_at from    vegetables v LEFT OUTER JOIN upload_file_morph ufm on    v.id = ufm.related_id LEFT OUTER JOIN upload_file uf on    ufm.upload_file_id = uf.id;',
    viewName: "vegetables_v")
class VegetableV {
  final int id;
  final String name;
  final String locale;
  final String? desc;
  final String? hash;
  final String? ext;

  @ColumnInfo(name: 'created_at')
  final int createTime;

  @ColumnInfo(name: 'updated_at')
  final int updateTime;

  VegetableV(
    this.id,
    this.name,
    this.locale,
    this.desc,
    this.hash,
    this.ext, {
    int? createTime,
    int? updateTime,
  })  : this.createTime = createTime ?? DateTime.now().millisecondsSinceEpoch,
        this.updateTime = updateTime ?? DateTime.now().millisecondsSinceEpoch;}

具体详情可参考 https://floor.codes/database-…

依据视图创立 ”Data Access Objects”[project_root]/lib/app/data/dao/vegetalbe_dao.dart

import 'package:floor/floor.dart';
import 'package:strapi_flutter_internation_poc/app/data/entity/vegetable.dart';

@dao
abstract class VegetableDao {@Query('SELECT * FROM vegetables_v')
  Future<List<VegetableV>> findAll();}

创立 Database 治理类[project_root]/lib/app/data/database.dart

import 'dart:async';
import 'package:floor/floor.dart';
import 'package:sqflite/sqflite.dart' as sqflite;
// daos
import 'dao/vegetable_dao.dart';
// entitys
import 'entity/vegetable.dart';

part 'database.g.dart'; // the generated code will be there

@Database(version: 1, entities: [Vegetable], views: [VegetableV])
abstract class AppDatabase extends FloorDatabase {VegetableDao get vegetableDao;}

运行 Floor 的代码生成器

flutter packages pub run build_runner build
[INFO] Generating build script...
[INFO] Generating build script completed, took 480ms

[INFO] Initializing inputs
[INFO] Reading cached asset graph...
[INFO] Reading cached asset graph completed, took 67ms

[INFO] Checking for updates since last build...
[INFO] Checking for updates since last build completed, took 651ms

[INFO] Running build...
[INFO] 1.1s elapsed, 0/1 actions completed.
[INFO] 2.2s elapsed, 0/1 actions completed.
[INFO] 4.0s elapsed, 0/1 actions completed.
[INFO] 8.4s elapsed, 0/1 actions completed.
[INFO] Running build completed, took 8.8s

[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 34ms

[INFO] Succeeded after 8.8s with 2 outputs (2 actions)

这里会生成一个与 database.dart 同目录的database.g.dart

应用 GetX 的 Service 计划创立 db 的 service [project_root]/lib/app/common/services/db_service.dart.dart

这里要特地留神一下

和 Floor 官网的文档介绍不同,Floor 会依据实体生成一个 sqlite 数据库,我这里会将现有的数据库文件提供给 Floor 应用不生成新的数据库文件。

import 'dart:io';
import 'package:get/get.dart';
import 'package:path/path.dart';
import 'package:floor/floor.dart';
import 'package:flutter/services.dart';
import 'package:sqflite/sqflite.dart';
import 'package:strapi_flutter_internation_poc/app/data/database.dart';

class DbService extends GetxService {static DbService get to => Get.find();

  late AppDatabase db;

  Future<DbService> init() async {
    final callback = Callback(onCreate: (database, version) {},
      onOpen: (database) {print('onOpen database');
        getDatabasesPath().then((value) => print(value));
      },
      onUpgrade: (database, startVersion, endVersion) {},);

    var dbDir = await getDatabasesPath();
    var dbPath = join(dbDir, "app_database.db");

    await deleteDatabase(dbPath);

    ByteData data = await rootBundle.load("assets/db/data.db");
    List<int> bytes =
        data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    await File(dbPath).writeAsBytes(bytes);

    db = await $FloorAppDatabase
        .databaseBuilder(dbPath)
        .addCallback(callback)
        .build();
    return this;
  }
}

实例化 DbService [project_root]/lib/main.dart

Future<void> main() async {WidgetsFlutterBinding.ensureInitialized();
  await initServices();

  runApp(
    GetMaterialApp(
      title: "Application",
      initialRoute: AppPages.INITIAL,
      getPages: AppPages.routes,
    ),
  );
}

Future<void> initServices() async {print('starting services ...');
  await Get.putAsync(() => DbService().init());
  print('All services started...');
}

批改 home_controller 代码读取 Sqlite 数据库 [project_root]/lib/app/modules/home/controllers/home_controller.dart

import 'package:get/get.dart';
import 'package:strapi_flutter_internation_poc/app/common/services/db_service.dart';
import 'package:strapi_flutter_internation_poc/app/data/entity/vegetable.dart';

class HomeController extends GetxController {final vegetables = Rx<List<VegetableV>>([]);

  @override
  void onInit() {super.onInit();
  }

  @override
  void onReady() {super.onReady();
  }

  Future<void> getAllVegetables() async {final result = await DbService.to.db.vegetableDao.findAll();
    vegetables.value = result;
  }

  @override
  void onClose() {}
}

简略测试一下

controller.getAllVegetables();

  Future<void> getAllVegetables() async {final result = await DbService.to.db.vegetableDao.findAll();
    vegetables.value = result;
    print(result);
  }

失去

I/flutter (7396): starting services ...
I/flutter (7396): onOpen database
I/flutter (7396): /data/user/0/com.nasawz.strapi_flutter_internation_poc.strapi_flutter_internation_poc/databases
I/flutter (7396): All services started...
[GETX] Instance "DbService" has been created
[GETX] Instance "DbService" has been initialized
[GETX] Instance "GetMaterialController" has been created
[GETX] Instance "GetMaterialController" has been initialized
[GETX] GOING TO ROUTE /home
[GETX] Instance "HomeController" has been created
[GETX] Instance "HomeController" has been initialized
I/flutter (7396): [Instance of 'VegetableV', Instance of 'VegetableV', Instance of 'VegetableV', Instance of 'VegetableV', Instance of 'VegetableV', Instance of 'VegetableV', Instance of 'VegetableV', Instance of 'VegetableV']

胜利!数据都读取进去了。

应用 GetX 的 Obx 个性把数据显示到界面上

import 'package:flutter/material.dart';

import 'package:get/get.dart';
import '../controllers/home_controller.dart';

class HomeView extends GetView<HomeController> {
  @override
  Widget build(BuildContext context) {controller.getAllVegetables();
    return Scaffold(
      appBar: AppBar(title: Text('Vegetables'),
        centerTitle: true,
      ),
      body: Obx(() => ListView.builder(
          itemCount: controller.vegetables.value.length,
          itemBuilder: (context, index) {var vegetable = controller.vegetables.value[index];
            return Padding(padding: const EdgeInsets.all(18.0),
              child: Container(
                child: Row(
                  children: [
                    Container(
                      // color: Colors.red,
                      child: Image.asset('strapi/public/uploads/thumbnail_${vegetable.hash}${vegetable.ext}',
                        fit: BoxFit.contain,
                        width: 140,
                        height: 140,
                      ),
                    ),
                    Container(
                      width: Get.width - 18 * 2 - 140 - 18,
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            vegetable.name,
                            style: Get.textTheme.headline6,
                          ),
                          Text(
                            vegetable.desc!,
                            style: Get.textTheme.subtitle1,
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            );
          })),
    );
  }
}


上一篇:整顿 Sqlite 数据库与图片

退出移动版