0% found this document useful (0 votes)
44 views8 pages

Lab7 Datapersistencewithsqlite

This document provides instructions for a lab activity to build a mobile application that uses SQLite database to persist data offline. The app allows users to record daily activities or "journal items" consisting of a title and description. SQLite will be used to store the journal items in a table with columns for id, title, description, and created date. The document outlines setting up the project, creating the database helper class to define methods for creating, reading, updating and deleting journal items from the SQLite database table.

Uploaded by

x
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views8 pages

Lab7 Datapersistencewithsqlite

This document provides instructions for a lab activity to build a mobile application that uses SQLite database to persist data offline. The app allows users to record daily activities or "journal items" consisting of a title and description. SQLite will be used to store the journal items in a table with columns for id, title, description, and created date. The document outlines setting up the project, creating the database helper class to define methods for creating, reading, updating and deleting journal items from the SQLite database table.

Uploaded by

x
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

Faculty of Computer Science and Information Technology

BIM30603/BIT34102 Mobile Application Development


Semester 1 2022/2023

Topic Lab 7 – Data Persistence with SQLite


Duration 2 hours
Tool/Software VS Code/Android Studio/Open Source IDE

Introduction
SQLite is a fast relational database that can be used to store data offline for mobile applications.
Whenever you need to store the data on the local then you need to use SQLite to persist the user data.
CRUD means create, read, update, and delete, the four essential operations of persistent storage.
Before using SQLite, you should know that SQLite is not available in a flutter SDK like Android but
we have a plugin sqflite that exactly performs all the operation on the database just like in Android and
iOS.
In this lab activity, we are going to build a small Flutter app that uses SQLite to persist data.

If you are new to SQLite, go through SQLite Tutorial site below:


http://www.sqlitetutorial.net/

The app we are going to make is an offline diary that lets users
record the activities they did during the day. For simplicity’s sake,
we will call each of these activities a “journal” or an “item”.
The app has a floating button that can be used to show a bottom
sheet. That bottom sheet contains 2 text fields corresponding to
“title” and “description”. These text fields are used to create a new
“item” or update an existing “item”.
The saved “items” are fetched from the SQLite database and
displayed with a list view. There are an update button and a delete
button associated with each “item”.

Database Structure
We are going to create an SQLite database called jurnal.db. It has only a single table named items.
Below is the structure of the table:
Column Type Description
id INTEGER The id of an activity
title TEXT The name of an activity
description TEXT The detail of an activity
createdAt TIMESTAMP The time that the item was created. It will be automatically added by SQLite

Implementation
1. Create a new Flutter project.

2. Install the sqflite plugin (note that the name has an “f”). Run the following line at Terminal window:

flutter pub add sqflite

Check in the dependencies section in pubspec.yaml file.


Faculty of Computer Science and Information Technology
BIM30603/BIT34102 Mobile Application Development
Semester 1 2022/2023

//...
dependencies:
flutter:
sdk: flutter

cupertino_icons: ^1.0.2 ## Add the 2 lines below


sqflite: # Needed for SQLite use
path_provider: # Needed to retrieve database file on device

dev_dependencies:
//...

3. In the lib folder, add a new file named sql_helper.dart. The project structure are as follows:
.
├── main.dart
└── sql_helper.dart

4. Create the table. We need to create a table to store information. For example, in our case, we create
a table called items that defines the data that can be stored. In this case, each item contains an id,
title, description and createdAt. Therefore, these will be represented as four columns in the
items table.

static Future<void> createTables(sql.Database database) async {


await database.execute("""CREATE TABLE items(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
title TEXT,
description TEXT,
createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
""");
}

5. Querying all data

static Future<List<Map<String, dynamic>>> getItems() async {


final db = await SQLHelper.db();
return db.query('items', orderBy: "id");
}

6. Querying single data by id

static Future<List<Map<String, dynamic>>> getItem(int id) async {


final db = await SQLHelper.db();
return db.query('items', where: "id = ?", whereArgs: [id], limit: 1);
}
Faculty of Computer Science and Information Technology
BIM30603/BIT34102 Mobile Application Development
Semester 1 2022/2023

7. Creating new data

static Future<int> createItem(String title, String? descrption) async {


final db = await SQLHelper.db();

final data = {'title': title, 'description': descrption};


final id = await db.insert('items', data,
conflictAlgorithm: sql.ConflictAlgorithm.replace);
return id;
}

8. Updating data

static Future<int> updateItem(


int id, String title, String? descrption) async {
final db = await SQLHelper.db();

final data = {
'title': title,
'description': descrption,
'createdAt': DateTime.now().toString()
};

final result =
await db.update('items', data, where: "id = ?", whereArgs: [id]);
return result;
}

9. Deleting data

static Future<void> deleteItem(int id) async {


final db = await SQLHelper.db();
try {
await db.delete("items", where: "id = ?", whereArgs: [id]);
} catch (err) {
debugPrint("Something went wrong when deleting an item: $err");
}
}
}
Faculty of Computer Science and Information Technology
BIM30603/BIT34102 Mobile Application Development
Semester 1 2022/2023

10. Full code in sql_helper.dart:


import 'package:flutter/foundation.dart';
import 'package:sqflite/sqflite.dart' as sql;

class SQLHelper {
static Future<void> createTables(sql.Database database) async {
await database.execute("""CREATE TABLE items(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
title TEXT,
description TEXT,
createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)"""
);
}

// id: the id of an item


// title, description: name and description of your activity
// created_at: the time that the item was created. It will be automatically handled by SQLite

static Future<sql.Database> db() async {


return sql.openDatabase(
'jurnal.db',
version: 1,
onCreate: (sql.Database database, int version) async {
await createTables(database);
},
);
}

// Create new item (journal)


static Future<int> createItem(String title, String? descrption) async {
final db = await SQLHelper.db();

final data = {'title': title, 'description': descrption};


final id = await db.insert('items', data,
conflictAlgorithm: sql.ConflictAlgorithm.replace);
return id;
}

// Read all items (journals)


static Future<List<Map<String, dynamic>>> getItems() async {
final db = await SQLHelper.db();
return db.query('items', orderBy: "id");
}

// Read a single item by id


// The app doesn't use this method, but I put here in case you want to see it
static Future<List<Map<String, dynamic>>> getItem(int id) async {
final db = await SQLHelper.db();
return db.query('items', where: "id = ?", whereArgs: [id], limit: 1);
}

// Update an item by id
static Future<int> updateItem(
int id, String title, String? descrption) async {
final db = await SQLHelper.db();

final data = {
'title': title,
'description': descrption,
'createdAt': DateTime.now().toString()
};

final result =
await db.update('items', data, where: "id = ?", whereArgs: [id]);
return result;
}
Faculty of Computer Science and Information Technology
BIM30603/BIT34102 Mobile Application Development
Semester 1 2022/2023

// Delete
static Future<void> deleteItem(int id) async {
final db = await SQLHelper.db();
try {
await db.delete("items", where: "id = ?", whereArgs: [id]);
} catch (err) {
debugPrint("Something went wrong when deleting an item: $err");
}
}
}

11. Full code in main.dart:


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

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

class MyApp extends StatelessWidget {


const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'My Jurnal',
theme: ThemeData(
primarySwatch: Colors.purple,
),
home: const HomePage());
}
}

class HomePage extends StatefulWidget {


const HomePage({Key? key}) : super(key: key);

@override
_HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {


// All journals
List<Map<String, dynamic>> _journals = [];

bool _isLoading = true;

// This function is used to fetch all data from the database


void _refreshJournals() async {
final data = await SQLHelper.getItems();
setState(() {
_journals = data;
_isLoading = false;
});
}

@override
void initState() {
super.initState();
_refreshJournals(); // Loading the diary when the app starts
}
Faculty of Computer Science and Information Technology
BIM30603/BIT34102 Mobile Application Development
Semester 1 2022/2023

final TextEditingController _titleController = TextEditingController();


final TextEditingController _descriptionController = TextEditingController();

// This function will be triggered when the floating button is pressed


// It will also be triggered when you want to update an item
void _showForm(int? id) async {
if (id != null) {
// id == null -> create new item
// id != null -> update an existing item
final existingJournal =
_journals.firstWhere((element) => element['id'] == id);
_titleController.text = existingJournal['title'];
_descriptionController.text = existingJournal['description'];
}

showModalBottomSheet(
context: context,
elevation: 5,
isScrollControlled: true,
builder: (_) => Container(
padding: EdgeInsets.only(
top: 15,
left: 15,
right: 15,
// this will prevent the soft keyboard from covering the text fields
bottom: MediaQuery.of(context).viewInsets.bottom + 120,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
TextField(
controller: _titleController,
decoration: const InputDecoration(hintText: 'Title'),
),
const SizedBox(
height: 10,
),

TextField(
controller: _descriptionController,
decoration: const InputDecoration(hintText: 'Description'),
),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () async {
// Save new journal
if (id == null) {
await _addItem();
}

if (id != null) {
await _updateItem(id);
}

// Clear the text fields


_titleController.text = '';
_descriptionController.text = '';

// Close the bottom sheet


Navigator.of(context).pop();
},
child: Text(id == null ? 'Create New' : 'Update'),
Faculty of Computer Science and Information Technology
BIM30603/BIT34102 Mobile Application Development
Semester 1 2022/2023

)
],
),
));
}

// Insert a new journal to the database


Future<void> _addItem() async {
await SQLHelper.createItem(
_titleController.text, _descriptionController.text);
_refreshJournals();
}

// Update an existing journal


Future<void> _updateItem(int id) async {
await SQLHelper.updateItem(
id, _titleController.text, _descriptionController.text);
_refreshJournals();
}

// Delete an item
void _deleteItem(int id) async {
await SQLHelper.deleteItem(id);
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Successfully deleted a journal!'),
));
_refreshJournals();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('My Jurnal'),
),
body: _isLoading
? const Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemCount: _journals.length,
itemBuilder: (context, index) => Card(
color: Colors.purple[200],
margin: const EdgeInsets.all(15),
child: ListTile(
title: Text(_journals[index]['title']),
subtitle: Text(_journals[index]['description']),
trailing: SizedBox(
width: 100,
child: Row(
children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () => _showForm(_journals[index]['id']),
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () =>
_deleteItem(_journals[index]['id']),
),
],
),
)),
),
),
Faculty of Computer Science and Information Technology
BIM30603/BIT34102 Mobile Application Development
Semester 1 2022/2023

floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => _showForm(null),
),
);
}
}

Conclusion
You’ve learned the fundamentals of SQLite and gone through an end-to-end example of using SQLite
in a Flutter app. From here, you can build more complex apps that store a lot of data offline.

You might also like