1. Introduction to SQLite in Android
SQLite is an embedded database engine that is self-contained, serverless, and zero-configuration. It’s included in Android by default, making it a convenient choice for apps needing local storage. SQLite supports standard SQL queries, transactions, and data manipulation.
2. Setting Up the Project
To start, create a new Android project in Android Studio and ensure that the necessary dependencies are added. The following dependencies should be included in your build.gradle
(app-level) file:
dependencies {
implementation "androidx.core:core-ktx:1.9.0"
implementation "androidx.appcompat:appcompat:1.5.1"
implementation "com.google.android.material:material:1.7.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
}
3. Creating the Database Schema
Define the schema for your SQLite database. For this example, let’s create a simple users
table with columns for id
, name
, and age
.
4. Database Helper Class
Create a class that extends SQLiteOpenHelper
to manage database creation and version management. This class will handle the creation, updating, and management of the database.
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
class DatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
companion object {
private const val DATABASE_NAME = "example.db"
private const val DATABASE_VERSION = 1
private const val TABLE_NAME = "users"
private const val COLUMN_ID = "id"
private const val COLUMN_NAME = "name"
private const val COLUMN_AGE = "age"
private const val SQL_CREATE_ENTRIES =
"CREATE TABLE $TABLE_NAME (" +
"$COLUMN_ID INTEGER PRIMARY KEY," +
"$COLUMN_NAME TEXT," +
"$COLUMN_AGE INTEGER)"
private const val SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS $TABLE_NAME"
}
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(SQL_CREATE_ENTRIES)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL(SQL_DELETE_ENTRIES)
onCreate(db)
}
}
5. CRUD Operations
Next, implement the CRUD (Create, Read, Update, Delete) operations in the DatabaseHelper
class.
Inserting Data
import android.content.ContentValues
fun insertUser(name: String, age: Int): Long {
val db = writableDatabase
val values = ContentValues().apply {
put(COLUMN_NAME, name)
put(COLUMN_AGE, age)
}
return db.insert(TABLE_NAME, null, values)
}
Reading Data
import android.database.Cursor
fun getAllUsers(): List<User> {
val db = readableDatabase
val projection = arrayOf(COLUMN_ID, COLUMN_NAME, COLUMN_AGE)
val cursor: Cursor = db.query(
TABLE_NAME,
projection,
null,
null,
null,
null,
null
)
val users = mutableListOf<User>()
with(cursor) {
while (moveToNext()) {
val userId = getLong(getColumnIndexOrThrow(COLUMN_ID))
val userName = getString(getColumnIndexOrThrow(COLUMN_NAME))
val userAge = getInt(getColumnIndexOrThrow(COLUMN_AGE))
users.add(User(userId, userName, userAge))
}
}
cursor.close()
return users
}
Updating Data
fun updateUser(id: Long, name: String, age: Int): Int {
val db = writableDatabase
val values = ContentValues().apply {
put(COLUMN_NAME, name)
put(COLUMN_AGE, age)
}
val selection = "$COLUMN_ID = ?"
val selectionArgs = arrayOf(id.toString())
return db.update(TABLE_NAME, values, selection, selectionArgs)
}
Deleting Data
fun deleteUser(id: Long): Int {
val db = writableDatabase
val selection = "$COLUMN_ID = ?"
val selectionArgs = arrayOf(id.toString())
return db.delete(TABLE_NAME, selection, selectionArgs)
}
6. Using the Database in Your App
To use the database helper in your app, instantiate it and call its methods. For example, to insert a new user:
val dbHelper = DatabaseHelper(context)
val newUserId = dbHelper.insertUser("John Doe", 30)
To read all users:
val users = dbHelper.getAllUsers()
for (user in users) {
println("User: ${user.name}, Age: ${user.age}")
}
7. Best Practices
- Use Singleton Pattern: Ensure a single instance of the database helper is used throughout the app to prevent memory leaks and redundant database connections.
- Use Async Tasks: Perform database operations on a background thread to avoid blocking the UI thread.
- Input Validation: Validate user inputs before inserting or updating data in the database.
- Database Migration: Handle database version upgrades and migrations carefully to preserve user data.
8. Conclusion
SQLite is a powerful tool for local data storage in Android apps. By following this guide, you can create a robust and efficient local database using SQLite and Kotlin. Remember to adhere to best practices to ensure smooth and efficient data handling in your applications.
This guide covers the fundamental aspects of integrating SQLite in an Android app with Kotlin. With this foundation, you can build more complex and feature-rich applications that handle data efficiently and securely. Happy coding!