Meta Description:
Tutorial lengkap membuat fitur login menggunakan SQLite di Kotlin Multiplatform (Android & iOS) dengan Compose Multiplatform, local database, session login, dan clean architecture.
Apa Itu Login SQLite di Kotlin Multiplatform?
Pada aplikasi mobile modern, login tidak selalu harus menggunakan server API. Untuk aplikasi offline-first, internal company apps, POS, asset tracking, atau prototype, login lokal menggunakan database SQLite sangat berguna.
Pada tutorial ini kita akan membuat:
✅ Login Android & iOS dengan satu codebase
✅ Database SQLite lokal
✅ Validasi username & password
✅ Session login sederhana
✅ UI modern Compose Multiplatform
✅ Clean Architecture project
Kita akan menggunakan:
- Kotlin Multiplatform
- Compose Multiplatform
- SQLite
- SQLDelight
Kenapa Menggunakan SQLite?
SQLite cocok digunakan untuk:
- Login offline
- Asset tracking
- Internal apps perusahaan
- POS system
- Mobile enterprise apps
- Penyimpanan credential lokal
Keunggulan SQLite:
- Ringan
- Tidak membutuhkan server
- Cepat
- Bisa berjalan offline
- Support Android dan iOS
Arsitektur Project
Struktur project:
composeApp
│
├── commonMain
│ ├── database
│ ├── model
│ ├── repository
│ ├── screen
│ └── viewmodel
│
├── androidMain
└── iosMain
Flow aplikasi:
Login Screen
↓
ViewModel
↓
Repository
↓
SQLite Database
↓
User Auth Success
Membuat Project Kotlin Multiplatform
Buka Android Studio:
New Project
→ Kotlin Multiplatform App
Pilih:
UI = Compose Multiplatform
Target = Android + iOS
Menambahkan Dependency SQLDelight
Edit:
build.gradle.kts
Tambahkan:
plugins {
id("app.cash.sqldelight")
}
Dependency:
commonMain.dependencies {
implementation(
"app.cash.sqldelight:runtime:2.0.2"
)
implementation(
"app.cash.sqldelight:coroutines-extensions:2.0.2"
)
}
Konfigurasi:
sqldelight {
databases {
create("AppDatabase") {
packageName.set("database")
}
}
}
Membuat Table User SQLite
Buat folder:
src/commonMain/sqldelight/database
File:
User.sq
Isi:
CREATE TABLE users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
password TEXT NOT NULL
);
insertUser:
INSERT INTO users(username,password)
VALUES (?, ?);
loginUser:
SELECT *
FROM users
WHERE username = ?
AND password = ?;
Penjelasan:
Table ini menyimpan:
id
username
password
Membuat Database Driver
File:
DatabaseFactory.kt
class DatabaseFactory(
driverFactory: DriverFactory
) {
val database = AppDatabase(
driverFactory.createDriver()
)
}
Driver Android
class AndroidDriverFactory(
private val context: Context
): DriverFactory {
override fun createDriver() =
AndroidSqliteDriver(
AppDatabase.Schema,
context,
"app.db"
)
}
Driver iOS
class IOSDriverFactory: DriverFactory {
override fun createDriver() =
NativeSqliteDriver(
AppDatabase.Schema,
"app.db"
)
}
Repository Login
File:
AuthRepository.kt
class AuthRepository(
private val database: AppDatabase
) {
fun register(
username: String,
password: String
) {
database.userQueries.insertUser(
username,
password
)
}
fun login(
username: String,
password: String
): Boolean {
return database
.userQueries
.loginUser(
username,
password
)
.executeAsOneOrNull() != null
}
}
Membuat UI Login
File:
LoginScreen.kt
@Composable
fun LoginScreen(
authRepository: AuthRepository
) {
var username by remember {
mutableStateOf("")
}
var password by remember {
mutableStateOf("")
}
var result by remember {
mutableStateOf("")
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
verticalArrangement =
Arrangement.Center
) {
Text(
"Login SQLite KMP",
style = MaterialTheme
.typography
.headlineMedium
)
Spacer(
Modifier.height(20.dp)
)
OutlinedTextField(
value = username,
onValueChange = {
username = it
},
label = {
Text("Username")
}
)
Spacer(
Modifier.height(10.dp)
)
OutlinedTextField(
value = password,
onValueChange = {
password = it
},
label = {
Text("Password")
}
)
Spacer(
Modifier.height(20.dp)
)
Button(
onClick = {
val success =
authRepository.login(
username,
password
)
result =
if(success)
"Login Berhasil"
else
"Login Gagal"
}
) {
Text("Login")
}
Spacer(
Modifier.height(20.dp)
)
Text(result)
}
}
Menambahkan User Dummy
Saat aplikasi pertama kali berjalan:
repository.register(
"admin",
"12345"
)
Login:
username: admin
password: 12345
Hasil Tampilan Aplikasi
UI yang dihasilkan:
- Input username
- Input password
- Tombol login
- Validasi login
- Pesan sukses / gagal
Menambahkan Session Login
Buat object:
object SessionManager {
var isLoggedIn = false
}
Ketika login berhasil:
SessionManager.isLoggedIn =
true
Password Hashing (Disarankan)
Jangan simpan password plaintext.
Gunakan hash:
SHA-256
bcrypt
Konsep:
password
↓
hash
↓
save database
Struktur Final Project
commonMain
│
├── database
│ ├── AppDatabase
│ └── User.sq
│
├── repository
│ └── AuthRepository
│
├── screen
│ └── LoginScreen
│
├── session
│ └── SessionManager
│
└── driver
├── AndroidDriverFactory
└── IOSDriverFactory
Kapan Harus Menggunakan SQLite Login?
Cocok untuk:
- Absensi
- Asset tracking
- Warehouse
- POS
- Internal apps
- Prototype
- Offline apps
Tidak cocok untuk:
- Banking online
- Marketplace besar
- Social media
- Public apps
Karena sebaiknya menggunakan server authentication + JWT.