Code Studio
Selasa, 05 Mei 2026
Android - Room Database
Room Database adalah bagian dari Android Jetpack yang menyediakan lapisan abstraksi di atas SQLite. Tujuannya adalah untuk mempermudah pengelolaan database lokal pada aplikasi Android dengan tetap memanfaatkan kekuatan penuh dari SQLite secara lebih aman dan efisien.
Secara sederhana, Room bertindak sebagai perantara antara kode Kotlin/Java Anda dengan database SQLite yang ada di sistem Android.
🧩 3 Komponen Utama Room
Ada tiga komponen penting yang harus ada agar Room bisa bekerja:
1. Entity
Entity adalah representasi dari tabel di dalam database. Anda mendefinisikan sebuah Data Class (di Kotlin) dan menandainya dengan anotasi @Entity. Setiap properti dalam kelas tersebut akan menjadi kolom di tabel database.
Anotasi Utama:
@PrimaryKey(wajib ada satu),@ColumnInfo(untuk mengubah nama kolom).
2. DAO (Data Access Object)
DAO adalah antarmuka (interface) yang digunakan untuk mendefinisikan metode akses data. Di sinilah Anda menulis query SQL (seperti SELECT, INSERT, DELETE, UPDATE).
Kelebihan: Room akan memeriksa syntax SQL Anda saat proses kompilasi (compile-time). Jika ada typo pada nama tabel, aplikasi tidak akan bisa di-build, sehingga mencegah error saat aplikasi dijalankan.
3. Room Database
Ini adalah titik akses utama dan pemegang koneksi ke database. Kelas ini harus berupa kelas abstrak yang mengekstensi RoomDatabase. Di sinilah Anda mendaftarkan Entity dan DAO.
🚀 Mengapa Menggunakan Room? (Kelebihan)
Keamanan Compile-time: Room mengecek query SQL Anda sebelum aplikasi dijalankan. Jika query salah, Room akan memberitahu Anda lewat pesan error saat kompilasi.
Boilerplate Code Berkurang: Anda tidak perlu lagi menulis kode panjang seperti
ContentValuesatauCursorsecara manual seperti pada SQLite tradisional.Integrasi dengan Library Lain: Room mendukung penuh Flow (Kotlin) atau LiveData untuk pembaruan data secara real-time (otomatis memperbarui UI saat data di DB berubah).
Migrasi yang Terstruktur: Room menyediakan sistem yang jelas untuk mengubah skema database (misalnya menambah kolom baru) tanpa menghapus data pengguna yang sudah ada.
🛠️ Contoh Implementasi Sederhana
Jika kita menerapkan Room pada aplikasi Marketplace Siswa yang Anda buat sebelumnya, berikut adalah gambaran kodenya:
Step 1: Entity (Tabel Produk)
@Entity(tableName = "produk_table")
data class Produk(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val nama: String,
val harga: Int,
val deskripsi: String
)
Step 2: DAO (Akses Data)
@Dao
interface ProdukDao {
@Query("SELECT * FROM produk_table ORDER BY id DESC")
fun getAllProduk(): Flow<List<Produk>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertProduk(produk: Produk)
@Delete
suspend fun deleteProduk(produk: Produk)
}
Step 3: Database Instance
@Database(entities = [Produk::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun produkDao(): ProdukDao
}
⚠️ Aturan Penting Room
Jangan di Main Thread: Operasi database (Insert, Update, Delete) tidak boleh dilakukan di Main Thread (thread UI) karena dapat menyebabkan aplikasi membeku (ANR - App Not Responding). Gunakan Coroutines (
suspend functions) untuk menjalankan operasi di background.Singleton Pattern: Sangat disarankan untuk membuat instance database sebagai Singleton agar tidak memakan banyak memori karena pembuatan koneksi database adalah proses yang "mahal".
Dengan Room, aplikasi Marketplace Anda nantinya tidak akan kehilangan data saat HP dimatikan atau aplikasi ditutup, karena data tersimpan permanen di penyimpanan internal ponsel.
entu, mari kita tingkatkan aplikasi MarketSiswa agar lebih tangguh. Dengan integrasi Room Database, data produk yang ditambahkan siswa akan tersimpan secara permanen di memori ponsel.
Berikut adalah perubahan kode yang terstruktur menjadi 3 bagian utama: Dependensi, Arsitektur Room, dan Update UI.
1. Tambahkan Dependensi
Buka file build.gradle.kts (Module: app) dan tambahkan baris berikut agar fitur Room bisa digunakan:
dependencies {
val room_version = "2.6.1"
implementation("androidx.room:room-runtime:$room_version")
implementation("androidx.room:room-ktx:$room_version")
kapt("androidx.room:room-compiler:$room_version") // Gunakan 'ksp' jika proyek Anda mendukung KSP
}
2. Implementasi Arsitektur Room
Kita akan mendefinisikan tabel, cara akses data, dan koneksi database.
import androidx.room.*
import kotlinx.coroutines.flow.Flow
// --- ENTITY (Tabel) ---
@Entity(tableName = "products")
data class ProductEntity(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val name: String,
val price: String,
val description: String
)
// --- DAO (Data Access Object) ---
@Dao
interface ProductDao {
@Query("SELECT * FROM products ORDER BY id DESC")
fun getAllProducts(): Flow<List<ProductEntity>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertProduct(product: ProductEntity)
}
// --- DATABASE INSTANCE ---
@Database(entities = [ProductEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun productDao(): ProductDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: android.content.Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"marketplace_db"
).build()
INSTANCE = instance
instance
}
}
}
}
3. Update UI (MainActivity.kt)
Sekarang kita hubungkan UI dengan Database menggunakan collectAsState agar daftar produk otomatis terupdate saat ada data baru masuk.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen() {
val context = androidx.compose.ui.platform.LocalContext.current
val db = remember { AppDatabase.getDatabase(context) }
val productDao = db.productDao()
// Mengambil data dari database secara real-time
val productList by productDao.getAllProducts().collectAsState(initial = emptyList())
var currentScreen by remember { mutableStateOf("home") }
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) },
// ... (TopBar & BottomBar sama seperti sebelumnya)
floatingActionButton = {
if (currentScreen == "home") {
ExtendedFloatingActionButton(
onClick = { currentScreen = "add" },
containerColor = MaterialTheme.colorScheme.primaryContainer
) {
Icon(Icons.Default.Add, contentDescription = null)
Text("Jual")
}
}
}
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
when (currentScreen) {
"home" -> HomeScreen(productList)
"add" -> AddProductScreen(
onProductAdded = { name, price, desc ->
scope.launch {
// Simpan ke database
productDao.insertProduct(
ProductEntity(name = name, price = price, description = desc)
)
currentScreen = "home"
snackbarHostState.showSnackbar("Produk tersimpan permanen!")
}
}
)
"profile" -> ProfileScreen()
}
}
}
}
@Composable
fun HomeScreen(products: List<ProductEntity>) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
item {
Text("Katalog Siswa", fontSize = 24.sp, fontWeight = FontWeight.ExtraBold)
Spacer(Modifier.height(8.dp))
}
items(products) { product ->
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(16.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(product.name, fontWeight = FontWeight.Bold, fontSize = 18.sp)
Text("Rp ${product.price}", color = MaterialTheme.colorScheme.primary)
Text(product.description, fontSize = 14.sp, color = Color.Gray)
}
}
}
}
}
@Composable
fun AddProductScreen(onProductAdded: (String, String, String) -> Unit) {
var name by remember { mutableStateOf("") }
var price by remember { mutableStateOf("") }
var desc by remember { mutableStateOf("") }
var isLoading by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
Column(modifier = Modifier.padding(24.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
OutlinedTextField(value = name, onValueChange = { name = it }, label = { Text("Nama") }, modifier = Modifier.fillMaxWidth())
OutlinedTextField(value = price, onValueChange = { price = it }, label = { Text("Harga") }, modifier = Modifier.fillMaxWidth())
OutlinedTextField(value = desc, onValueChange = { desc = it }, label = { Text("Deskripsi") }, modifier = Modifier.fillMaxWidth())
Button(
onClick = {
isLoading = true
scope.launch {
delay(800) // Simulasi UX loading
onProductAdded(name, price, desc)
isLoading = false
}
},
modifier = Modifier.fillMaxWidth(),
enabled = name.isNotBlank() && !isLoading
) {
if (isLoading) CircularProgressIndicator(size = 20.dp) else Text("Simpan")
}
}
}
Apa yang berubah?
Penggunaan Flow: Di
ProductDao, kita menggunakanFlow<List<ProductEntity>>. Ini membuat UI "berlangganan" pada database. Begitu data di DB berubah, UI otomatis update tanpa perlu refresh manual.Coroutine Scope: Proses simpan (
insertProduct) ditandai sebagaisuspend, jadi kita menjalankannya di dalamscope.launchagar tidak mengganggu kelancaran UI.Data Persisten: Sekarang, silakan coba tambah produk, lalu tutup aplikasi sepenuhnya (bahkan hapus dari Recent Apps). Saat dibuka kembali, produk Anda akan tetap ada di sana!
Apakah Anda ingin menambahkan fitur Hapus Produk (Delete) dengan cara menggeser (swipe) kartu produk?</List
React - Deploy Aplikasi
Panduan Deploy Aplikasi Marketplace Siswa
Dokumen ini menjelaskan langkah-langkah untuk mempublikasikan (deploy) aplikasi React Anda ke internet agar dapat diakses secara publik.
1. Persiapan Awal
Pastikan Anda sudah memiliki lingkungan pengembangan lokal yang siap:
Node.js terinstall di komputer.
Git terinstall untuk mengelola kode.
Akun di GitHub, Vercel, atau Netlify.
2. Membuat Proyek React Lokal
Jika Anda belum memiliki struktur proyek yang lengkap, gunakan Vite (rekomendasi terbaru):
Buka terminal/CMD dan jalankan:
npm create vite@latest marketplace-siswa -- --template react cd marketplace-siswa npm installInstall dependensi yang dibutuhkan oleh aplikasi:
npm install lucide-react npm install -D tailwindcss border-color postcss autoprefixer npx tailwindcss init -pSalin kode dari file
marketplace_siswa.jsxke dalamsrc/App.jsxdi proyek baru Anda.
3. Konfigurasi Tailwind CSS
Agar tampilan sesuai, pastikan file tailwind.config.js Anda diatur seperti ini:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Dan tambahkan direktif Tailwind di src/index.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
4. Opsi Deployment
Opsi A: Menggunakan Vercel (Paling Mudah)
Buat repositori baru di GitHub dan unggah (push) kode Anda ke sana.
Buka Vercel.
Klik "Add New" > "Project".
Hubungkan akun GitHub Anda dan pilih repositori
marketplace-siswa.Klik "Deploy". Vercel akan mendeteksi Vite secara otomatis.
Opsi B: Menggunakan Netlify
Buka Netlify.
Login dan pilih "Add new site" > "Import from existing project".
Pilih GitHub dan tentukan repositorinya.
Pastikan Build Command adalah
npm run builddan Publish directory adalahdist.Klik "Deploy site".
Opsi C: Drag & Drop (Tanpa GitHub)
Jalankan perintah build di terminal lokal Anda:
npm run buildFolder bernama
distakan muncul di proyek Anda.Buka Netlify, masuk ke menu Sites, lalu tarik dan lepas (drag & drop) folder
disttersebut ke area yang disediakan.
5. Tips Tambahan
Custom Domain: Baik Vercel maupun Netlify memberikan subdomain gratis (contoh:
marketplace-siswa.vercel.app). Anda bisa menghubungkan domain.comatau.idmilik sendiri di menu pengaturan.Update Kode: Jika Anda menggunakan metode GitHub, setiap kali Anda melakukan
git push, situs Anda akan diperbarui secara otomatis.
Dibuat untuk mempermudah siswa dalam mempublikasikan karya mereka.
React - Deploy
https://www.youtube.com/watch?v=Ey_90l9GaAw https://www.youtube.com/watch?v=G6D9cBaLViA https://www.youtube.com/watch?v=hn1IkJk24ow https:...
-
Versi 1 Versi 2 Versi 3 Versi 4 Aplikasi ini versi GUI dengan Swing mempunyai form input catatan...
-
https://www.geeksforgeeks.org/javascript/form-validation-using-javascript/ https://www.geeksforgeeks.org/html/javascript-application-for-e...
-
https://www.youtube.com/watch?v=wUw8eLeJH0A&list=PLz_5rPRIvGECVDOGY8fMs3-8uZVlyJ-gr https://webdesignmastery.github.io/Royal_Hotel_31-...

