Sparround

Room və lokal saxlama: DataStore vs SharedPreferences

Room — SQLite üstündə compile-time yoxlanılan ORM qatı. Üç tikinti daşı:

  • @Entity — cədvəl (data class)
  • @Dao — sorğu interfeysi: @Query-lər compile vaxtı SQL-ə qarşı yoxlanılır
  • @Database — DB holder, versiya və migration-ların sahibi

Güclü tərəfləri: Flow<List<T>> qaytaran sorğular — cədvəl dəyişəndə avtomatik yeni emissiya (reaktiv UI-ın təməli); suspend DAO metodları; @Transaction ilə atomik əməliyyatlar; migration mexanizmi.

Kiçik data üçün:

  • SharedPreferences — köhnə key-value: sinxron API (commit() disk yazışı ilə bloklayır), type-safety yoxdur, multi-process zəif.
  • DataStore — müasir əvəzedici: Flow əsaslı, suspend API (main thread-i bloklamır), Preferences və Proto (typed schema) variantları. Rəsmi tövsiyə: yeni kod DataStore işlətsin.

Migration müsahibə klassikasıdır: versiya artırılır, Migration(1, 2) obyekti SQL ilə yazılır; migration verilməsə → crash və ya fallbackToDestructiveMigration ilə data itkisi.

kotlin
@Entity(tableName = "transactions")
data class TransactionEntity(
    @PrimaryKey val id: String,
    val accountId: String,
    val amountMinor: Long,
    val createdAt: Long
)

@Dao
interface TransactionDao {
    @Query("SELECT * FROM transactions WHERE accountId = :accountId ORDER BY createdAt DESC")
    fun observeByAccount(accountId: String): Flow<List<TransactionEntity>>

    @Upsert
    suspend fun upsertAll(items: List<TransactionEntity>)
}

// v1 → v2: yeni sütun
val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE transactions ADD COLUMN category TEXT")
    }
}

Room.databaseBuilder(context, BankDb::class.java, "bank.db")
    .addMigrations(MIGRATION_1_2)
    .build()

Room-un əsas hissələri və migration

Bank tətbiqində lokal saxlama qaydası: həssas data (token, PIN həşi) nə SharedPreferences, nə adi DataStore-da açıq saxlanmamalıdır — Keystore ilə şifrələmə və ya EncryptedSharedPreferences (təhlükəsizlik stage-ində ətraflı). Room DB-də isə minimum həssas sahə prinsipi: kart nömrəsinin tam halı lokalda ümumiyyətlə saxlanılmır, yalnız maskalı forma.

🛠 Tapşırıq

Room ilə transactions cədvəli qur: @Entity, @Dao (Flow qaytaran sorğu ilə), @Database.

  • UI-da (və ya testdə) Flow-a abunə ol, DB-yə yeni sətir yaz və əl ilə heç nə çağırmadan siyahının yeniləndiyini gör.
  • Yeni sütun əlavə et, versiyanı artır — migration vermədən işə sal və crash-ı gör; sonra Migration(1,2) yazıb düzəlt.
  • Bir seçimi DataStore-da saxla və Flow ilə oxu.

Bitdi sayılır: migration-suz nə baş verdiyini və fallbackToDestructiveMigration-ın niyə təhlükəli olduğunu deyirsənsə.

📚 Mənbələr və sənədlər