در گذشتههای نه چندان دور اگر یه توسعهدهنده اندروید میخواست با دیتابیس کار کنه مجبور بود با خیلی از کارها مثل ساختن table و ذخیر کردن اطلاعات بصورت دستی و کوئری های مختلف کارشو پیش ببره اما با اومدن کتابخونه هایی مثل Room این کارا تا حد زیادی ساده تر شدن.
قبل از شروع کار نیاز داریم که لایبراری های زیر رو به پروژه و در قسمت dependencies فایل build.gradle اپمون اضاف کنیم.
def room_version = "2.2.6" implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" // optional - Kotlin Extensions and Coroutines support for Room implementation "androidx.room:room-ktx:$room_version"
حالا وقته آشنا شدن با قسمتهای مختلف Room هست :
@Entity
@Entity class Product : Serializable { @PrimaryKey(autoGenerate = true) var id = 0 @ColumnInfo(name = "name") var name: String? = null @ColumnInfo(name = "desc") var desc: String? = null }
این قسمت مشخصات table ای که لازم داریم رو تعیین میکنه
@Dao(data access objects)
@Dao interface ProductDao { @get:Query("SELECT * FROM product") val all: List<Product?>? @Insert fun insert(product: Product?) @Delete fun delete(product: Product?) @Update fun update(product: Product?) }
این قسمت وظیفه ورود اطلاعات، حذف و ... رو بر عهده داره.
حالا موقع به کار بردن دوتا کلاس بالا هستش :
در اینجا به دوتا کلاس جداگونه دیگه هم احتیاج داریم که یکی وظیفه ارتباط با دیتابیس یا ساخت یک access point رو بر عهده داره و دومی وظیفه ساخت دیتابیس.
@Database(entities = [Product::class] , version = 1) public abstract class AppDatabase : RoomDatabase() { abstract fun productDao(): ProductDao? }
class DatabaseClient private constructor(mCtx: Context) { private val mCtx = mCtx val appDatabase: AppDatabase = Room .databaseBuilder(mCtx, AppDatabase::class.java, "databse_name") .build() companion object { private var mInstance: DatabaseClient? = null @Synchronized fun getInstance(mCtx: Context): DatabaseClient? { if (mInstance == null) { mInstance = DatabaseClient(mCtx) } return mInstance } } }
در این کلاس دوتا نکته وجود داره :
1: برای اینکه ساخت هرباره یک object از DatabaseClient به اصطلاح expensive هست و کمی کاهش سرعت در اپ رو میتونه ایجاد کنه از دیزاینپترن Singleton استفاده شده تا فقط یکبار object ایجاد بشه و بار های بعدی از دیتای cache شده استفاده بشه.
2: برای استفاده از دیتابیس از main Thread برنامه نمیتونیم استفاده کنیم چرا که هم باعث قفل شدن لحظهای برنامه میشه و هم اینکه سیستمعامل اجازه این کارو نمیده و حتما باید از thread جداگونهای استفاده بشه برای همین موضوع از Synchronized@ استفاده کردیم تا تردهای مختلف همزمان نتونن از دیتابیس استفاده کنن و داده ها با اختلال روبرو نشن.
حالا موقع استفاده از کارهاییه که انجام دادیم : ایجاد یک داده جدید در table product
var thread = Thread(Runnable { var product = Product(); product.name = "apple" product.desc = "delicious apples from Semirom of Iran" DatabaseClient.getInstance(context)?.appDatabase!! .productDao()!! .insert(product) }) thread.start()
خلاصه : ما در واقع چهار کلاس اصلی ایجاد کردیم که
Product (ایجاد مشخصات تیبل),
ProductDao (ایجاد ، حذف ، اپدیت آبجکت های تیبل),
DatabseClient ( ساخت دیتابیس),
AppDatabase (ایجاد رابط برای ارتباط با دیتابیس)