Mobiilikehitys Flutterilla · Oppitunti

SQLite-tietokannan integrointi

Integroikaa SQLite-tietokantoja Flutter-sovellukseen `sqflite`-paketin avulla rakenteisten ja relaatiomuotoisten tietojen tallentamista varten.

Oppitunti 2/412 vaihetta

SQLite-tietokannan integrointi on ilmainen Mobiilikehitys Flutterilla-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Mobiilikehitys Flutterilla-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Mobiilikehitys Flutterilla-kurssilla on yhteensä 4 oppituntia.

Tietojen tallentaminen SQLiten avulla

Tervetuloa! Tässä oppitunnissa opit integroimaan paikallisen tietokannan Flutter-sovellukseesi SQLiten avulla.

SQLite on kevyt, palvelimeton, itsenäinen ja tapahtumapohjainen relaatiotietokantamoottori. Se sopii erinomaisesti rakenteisten tietojen tallentamiseen suoraan käyttäjän laitteelle ilman erillistä palvelinprosessia.

`sqflite`-paketin valmistelu

SQLite-tietokantojen käyttämiseen Flutterissa käytämme suosittua sqflite-pakettia. Se tarjoaa monipuolisen rajapinnan SQLite-tietokantoihin.

Lisää se (yhdessä tietokantatiedostojen hallintaan tarvittavien path_provider- ja path-pakettien kanssa) ensin pubspec.yaml-tiedoston dependencies-osioon:

  • dependencies:
  • flutter:
  • sdk: flutter
  • sqflite: ^2.3.0
  • path_provider: ^2.1.1
  • path: ^1.8.3

Suorita päätteessä komento flutter pub get lisäämisen jälkeen.

Tietokannan apuluokka

Hyvä käytäntö on luoda erillinen "helper"-luokka tietokantatoimintojen hallintaa varten. Näin tietokannan avaamiseen, luomiseen ja kyselyiden suorittamiseen liittyvä logiikka keskitetään yhteen paikkaan.

Tämä luokka käsittelee yleensä seuraavia asioita:

  • Tietokantayhteyden alustaminen ja avaaminen.
  • Taulukoiden luominen tietokannan ensimmäisen avauksen yhteydessä.
  • Tietokannan yhden ilmentymän (singleton) tarjoaminen koko sovellukselle.
  • Suorien SQL-kyselyiden piilottaminen.

Tietokannan alustaminen

Aloitetaan DatabaseHelper-luokan rakentaminen. openDatabase-funktio on keskeinen. Se saa parametrikseen tietokantatiedoston polun ja alkuasetukset määrittävän onCreate-takaisinkutsun.

Tietokannan voi avata tai luoda seuraavasti:

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

// NOTE: getDatabasesPath() requires Flutter context.
// This main method is for demonstration.
// In a real Flutter app, _initDatabase would be called
// from a StatefulWidget or similar.

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  static Database? _database;

  factory DatabaseHelper() {
    return _instance;
  }

  DatabaseHelper._internal();

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  Future<Database> _initDatabase() async {
    // Get the default databases location for the platform
    String path = await getDatabasesPath();
    String dbPath = join(path, 'item_database.db');

    return await openDatabase(
      dbPath,
      version: 1,
      onCreate: (db, version) {
        // Table creation logic will go here
        print('Database created or opened.');
      },
    );
  }
}

void main() async {
  // This main is illustrative. sqflite operations need a
  // running Flutter app context to fully function (e.g. for getDatabasesPath).
  // When run in a Flutter app, DatabaseHelper().database
  // would ensure the DB is initialized.
  print('DatabaseHelper class defined.');
}

Ensimmäisen taulukon luominen

Määritellään _initDatabase-funktion onCreate-takaisinkutsussa tietokannan rakenne vakiomuotoisen SQL:n avulla. Luodaan yksinkertainen items-taulukko.

Jokaisella kohteella on id (pääavain), name (teksti) ja quantity (kokonaisluku).

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

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  static Database? _database;
  factory DatabaseHelper() { return _instance; }
  DatabaseHelper._internal();
  Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; }
  Future<Database> _initDatabase() async {
    String path = await getDatabasesPath();
    String dbPath = join(path, 'item_database.db');
    return await openDatabase(dbPath, version: 1,
      onCreate: (db, version) async {
        // SQL to create the items table
        await db.execute(
          '''
          CREATE TABLE items(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT,
            quantity INTEGER
          )
          '''
        );
        print('Table "items" created successfully.');
      },
    );
  }
}

void main() async {
  // This main is illustrative. In a Flutter app,
  // calling DatabaseHelper().database would trigger
  // _initDatabase and the onCreate callback.
  print('Database helper configured for table creation.');
}

Tietomallin luominen

Jotta tietokantatietueiden käsittely olisi helppoa, määrittele Dart-luokka, joka vastaa taulukkosi rakennetta. Näin tiedot on helppo muuntaa Dart-objektien ja tietokantarivien välillä (rivit esitetään yleensä muodossa Map).

Tässä on Item-mallimme sekä sen toMap()- ja fromMap()-menetelmät:

class Item {
  final int? id;
  final String name;
  final int quantity;

  Item({this.id, required this.name, required this.quantity});

  // Convert an Item into a Map. Keys must match DB column names.
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'quantity': quantity,
    };
  }

  // Create an Item object from a Map (database row).
  static Item fromMap(Map<String, dynamic> map) {
    return Item(
      id: map['id'],
      name: map['name'],
      quantity: map['quantity'],
    );
  }

  @override
  String toString() {
    return 'Item(id: $id, name: $name, quantity: $quantity)';
  }
}

void main() {
  final myItem = Item(id: 1, name: 'Apple', quantity: 5);
  print('Created Item: ${myItem.toString()}');
  print('Converted to Map: ${myItem.toMap()}');

  final itemMap = {'id': 2, 'name': 'Banana', 'quantity': 3};
  final itemFromMap = Item.fromMap(itemMap);
  print('Item from Map: ${itemFromMap.toString()}');
}

Tietojen lisääminen

Lisätään nyt DatabaseHelper-luokkaan menetelmä uusien kohteiden lisäämistä varten. insert-menetelmä saa parametrikseen taulukon nimen ja Map-rakenteen (meidän tapauksessamme Item.toMap()-menetelmän palauttaman arvon).

Se palauttaa juuri lisätyn rivin id-arvon.

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

// Item class (from previous scene, for self-containment)
class Item {
  final int? id; final String name; final int quantity;
  Item({this.id, required this.name, required this.quantity});
  Map<String, dynamic> toMap() { return {'id': id, 'name': name, 'quantity': quantity}; }
  static Item fromMap(Map<String, dynamic> map) { return Item(id: map['id'], name: map['name'], quantity: map['quantity']); }
  @override
  String toString() { return 'Item(id: $id, name: $name, quantity: $quantity)'; }
}

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  static Database? _database;
  factory DatabaseHelper() { return _instance; }
  DatabaseHelper._internal();
  Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; }
  Future<Database> _initDatabase() async {
    String path = await getDatabasesPath();
    String dbPath = join(path, 'item_database.db');
    return await openDatabase(dbPath, version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE items(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, quantity INTEGER)
          ''');
      },
    );
  }

  Future<int> insertItem(Item item) async {
    final db = await database;
    return await db.insert(
      'items',
      item.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace, // Replace if ID exists
    );
  }
}

void main() async {
  // Illustrative main. In a Flutter app, you'd call:
  // final dbHelper = DatabaseHelper();
  // final newItem = Item(name: 'Milk', quantity: 2);
  // int id = await dbHelper.insertItem(newItem);
  // print('Inserted item with id: $id');
  print('Item insertion logic defined in DatabaseHelper.');
}

Tietojen kysely

Voit lukea tietoja käyttämällä query-menetelmää. Se palauttaa arvon List>, jonka muunnat sen jälkeen takaisin Dartin Item-objekteiksi käyttämällä Item.fromMap()-menetelmää.

Voit hakea kaikki kohteet tai rajata haun tiettyihin kohteisiin where-ehtojen avulla.

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

// Item class (for self-containment)
class Item {
  final int? id; final String name; final int quantity;
  Item({this.id, required this.name, required this.quantity});
  Map<String, dynamic> toMap() { return {'id': id, 'name': name, 'quantity': quantity}; }
  static Item fromMap(Map<String, dynamic> map) { return Item(id: map['id'], name: map['name'], quantity: map['quantity']); }
  @override
  String toString() { return 'Item(id: $id, name: $name, quantity: $quantity)'; }
}

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  static Database? _database;
  factory DatabaseHelper() { return _instance; }
  DatabaseHelper._internal();
  Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; }
  Future<Database> _initDatabase() async {
    String path = await getDatabasesPath();
    String dbPath = join(path, 'item_database.db');
    return await openDatabase(dbPath, version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE items(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, quantity INTEGER)
          ''');
      },
    );
  }

  Future<List<Item>> getItems() async {
    final db = await database;
    // Query all the items from the table
    final List<Map<String, dynamic>> maps = await db.query('items');

    // Convert the List<Map<String, dynamic>> into a List<Item>.
    return List.generate(maps.length, (i) {
      return Item.fromMap(maps[i]);
    });
  }
}

void main() async {
  // Illustrative main. In a Flutter app, you'd call:
  // final dbHelper = DatabaseHelper();
  // await dbHelper.insertItem(Item(name: 'Bread', quantity: 1));
  // final items = await dbHelper.getItems();
  // print('Retrieved items: $items');
  print('Item query logic defined in DatabaseHelper.');
}

Tietojen päivittäminen

Voit muuttaa olemassa olevaa tietuetta käyttämällä update-menetelmää. Anna sille taulukon nimi, uudet tiedot Map-rakenteena sekä where-ehto, joka määrittää päivitettävät tietueet.

Käytä aina whereArgs-parametria paikkamerkkien (?) kanssa, jotta arvot välitetään turvallisesti ja SQL-injektio estetään.

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

// Item class (for self-containment)
class Item {
  final int? id; final String name; final int quantity;
  Item({this.id, required this.name, required this.quantity});
  Map<String, dynamic> toMap() { return {'id': id, 'name': name, 'quantity': quantity}; }
  static Item fromMap(Map<String, dynamic> map) { return Item(id: map['id'], name: map['name'], quantity: map['quantity']); }
  @override
  String toString() { return 'Item(id: $id, name: $name, quantity: $quantity)'; }
}

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  static Database? _database;
  factory DatabaseHelper() { return _instance; }
  DatabaseHelper._internal();
  Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; }
  Future<Database> _initDatabase() async {
    String path = await getDatabasesPath();
    String dbPath = join(path, 'item_database.db');
    return await openDatabase(dbPath, version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE items(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, quantity INTEGER)
          ''');
      },
    );
  }

  Future<int> updateItem(Item item) async {
    final db = await database;
    return await db.update(
      'items',
      item.toMap(),
      where: 'id = ?', // Specify which item to update
      whereArgs: [item.id],
    );
  }
}

void main() async {
  // Illustrative main. In a Flutter app, you'd call:
  // final dbHelper = DatabaseHelper();
  // // Assume item with id 1 exists
  // var updatedItem = Item(id: 1, name: 'Milk', quantity: 3);
  // int count = await dbHelper.updateItem(updatedItem);
  // print('Updated $count item(s).');
  print('Item update logic defined in DatabaseHelper.');
}

Tietojen poistaminen

Voit poistaa tietueita tietokannasta käyttämällä delete-menetelmää. Kuten update-menetelmässä, anna sille taulukon nimi sekä where-ehto ja whereArgs-parametri poistettavien tietueiden määrittämistä varten.

Menetelmä palauttaa poistettujen rivien lukumäärän.

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

// Item class (for self-containment)
class Item {
  final int? id; final String name; final int quantity;
  Item({this.id, required this.name, required this.quantity});
  Map<String, dynamic> toMap() { return {'id': id, 'name': name, 'quantity': quantity}; }
  static Item fromMap(Map<String, dynamic> map) { return Item(id: map['id'], name: map['name'], quantity: map['quantity']); }
  @override
  String toString() { return 'Item(id: $id, name: $name, quantity: $quantity)'; }
}

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  static Database? _database;
  factory DatabaseHelper() { return _instance; }
  DatabaseHelper._internal();
  Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; }
  Future<Database> _initDatabase() async {
    String path = await getDatabasesPath();
    String dbPath = join(path, 'item_database.db');
    return await openDatabase(dbPath, version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE items(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, quantity INTEGER)
          ''');
      },
    );
  }

  Future<int> deleteItem(int id) async {
    final db = await database;
    return await db.delete(
      'items',
      where: 'id = ?',
      whereArgs: [id],
    );
  }
}

void main() async {
  // Illustrative main. In a Flutter app, you'd call:
  // final dbHelper = DatabaseHelper();
  // // Assume item with id 1 exists
  // int count = await dbHelper.deleteItem(1);
  // print('Deleted $count item(s).');
  print('Item deletion logic defined in DatabaseHelper.');
}

SQLite-toimintojen tietovisa

Oletetaan, että items-taulukossa on sarakkeet id (INTEGER), name (TEXT) ja quantity (INTEGER).

Mitä sqflite-menetelmää käyttäisit hakeaksesi kaikki kohteet, joiden määrä on suurempi kuin 10?

Kertaus: SQLite ja `sqflite`

Hienoa työtä! Olet oppinut SQLite-tietokannan integroinnin perusteet Flutter-sovellukseen sqflite-paketin avulla.

Tärkeimmät asiat:

  • SQLite on kevyt paikallinen relaatiotietokanta.
  • sqflite-paketti tarjoaa Dart-rajapinnat SQLitea varten.
  • DatabaseHelper-luokka keskittää tietokantatoiminnot, kuten taulukoiden luomisen, avaamisen ja hallinnan.
  • Voit suorittaa tavallisia CRUD-toimintoja (Create, Read, Update, Delete) käyttämällä insert-, query-, update- ja delete-menetelmiä.
  • Datamalliluokka (kuten Item) helpottaa tietojen muuntamista Dart-objektien ja tietokantarivien välillä.

Nämä tiedot ovat olennaisia, kun rakennat vankkoja Flutter-sovelluksia, jotka säilyttävät tietoja paikallisesti!

Aloita maksutta

Opi Dart tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
22
Oppitunnit
88

Usein kysytyt kysymykset

Onko oppitunti ”SQLite-tietokannan integrointi” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Mobiilikehitys Flutterilla-oppimispolun 3 oppituntia, myös oppitunnin “SQLite-tietokannan integrointi”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Mobiilikehitys Flutterilla-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”SQLite-tietokannan integrointi”?

Integroikaa SQLite-tietokantoja Flutter-sovellukseen `sqflite`-paketin avulla rakenteisten ja relaatiomuotoisten tietojen tallentamista varten. Harjoittelet Mobiilikehitys Flutterilla-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Mobiilikehitys Flutterilla-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Mobiilikehitys Flutterilla-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”SQLite-tietokannan integrointi”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Mobiilikehitys Flutterilla-oppitunnilla?

Kyllä. Jokainen Mobiilikehitys Flutterilla-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Shared Preferences tietojen tallennukseen
  2. SQLite-tietokannan integrointi
  3. Tiedostojärjestelmän toiminnot
  4. Hive ja paikallinen NoSQL-tallennus
← Takaisin: Mobiilikehitys Flutterilla