SQLite
 sql >> Base de Dados >  >> RDS >> SQLite

Como criar um aplicativo de internacionalização offline:use o banco de dados SQLite


https://pub.dev/packages/floor

Configure a referência pubspec.yaml da biblioteca dependente no projeto Flutter

dependencies:
  flutter:
    sdk: flutter
  floor: ^1.2.0

dev_dependencies:
  floor_generator: ^1.2.0
  build_runner: ^2.1.2

Crie entidade e visualize [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;
}


Para detalhes específicos, consulte https://floor.codes/database-views/

Crie "Objetos de acesso a dados" de acordo com a visualização[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();
}


Criar classe de gerenciamento de banco de dados [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;
}

Gerador de código do Run 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)

Isso gerará um database.g.dart no mesmo diretório que database.dart

Use o esquema de serviço do GetX para criar o serviço db [project_root]/lib/app/common/services/db_service.dart.dart

Por favor, preste atenção especial aqui

Ao contrário da documentação oficial do Floor, o Floor irá gerar um banco de dados sqlite baseado na entidade. Fornecerei os arquivos de banco de dados existentes ao Floor para uso sem gerar novos arquivos de banco de dados.

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;
  }
}

Instanciar 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...');
}

Modifique o código home_controller para ler o banco de dados 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() {}
}


Teste brevemente

controller.getAllVegetables();

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

Fora

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']

sucesso! Os dados são lidos.

Use o recurso Obx do GetX para exibir dados na interface

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,
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            );
          })),
    );
  }
}