অ্যান্ড্রয়েড জেটপ্যাকের রুম অংশ ব্যবহার করে স্থানীয় ডেটাবেসে ডেটা সংরক্ষণ করুন।

কোটলিন মাল্টিপ্ল্যাটফর্ম দিয়ে চেষ্টা করুন
কোটলিন মাল্টিপ্ল্যাটফর্ম অন্যান্য প্ল্যাটফর্মের সাথে ডেটাবেস লেয়ার শেয়ার করার সুযোগ দেয়। KMP-তে কীভাবে রুম ডেটাবেস সেট আপ এবং ব্যবহার করতে হয় তা জানুন।

যেসব অ্যাপ উল্লেখযোগ্য পরিমাণে স্ট্রাকচার্ড ডেটা নিয়ে কাজ করে, তারা সেই ডেটা স্থানীয়ভাবে সংরক্ষণ করলে ব্যাপকভাবে উপকৃত হতে পারে। এর সবচেয়ে সাধারণ ব্যবহার হলো প্রাসঙ্গিক ডেটা ক্যাশ করে রাখা, যাতে ডিভাইসটি নেটওয়ার্ক অ্যাক্সেস করতে না পারলেও আপনার ব্যবহারকারীরা অফলাইনে থাকা অবস্থায়ও সেই কন্টেন্ট ব্রাউজ করতে পারেন।

Room পার্সিস্টেন্স লাইব্রেরিটি SQLite-এর উপর একটি অ্যাবস্ট্রাকশন লেয়ার প্রদান করে, যা SQLite-এর সম্পূর্ণ শক্তিকে কাজে লাগানোর পাশাপাশি সাবলীলভাবে ডেটাবেস অ্যাক্সেস করতে দেয়। বিশেষত, Room নিম্নলিখিত সুবিধাগুলো প্রদান করে:

  • SQL কোয়েরিগুলোর কম্পাইল-টাইম যাচাইকরণ।
  • সুবিধাজনক টীকা যা পুনরাবৃত্তিমূলক এবং ত্রুটিপ্রবণ বয়লারপ্লেট কোড হ্রাস করে।
  • সুবিন্যস্ত ডাটাবেস মাইগ্রেশন পথ।

আমরা সরাসরি SQLite API ব্যবহার করার পরিবর্তে Room ব্যবহার করার পরামর্শ দিই।

সেটআপ

আপনার অ্যাপে Room ব্যবহার করতে, আপনার মডিউলের build.gradle.kts ফাইলে নিম্নলিখিত ডিপেন্ডেন্সিগুলো যোগ করুন। Room 3.0-এর অ্যানোটেশন প্রসেসিংয়ের জন্য KSP প্রয়োজন।

কোটলিন

dependencies {
    val room_version = "3.0.1"

    implementation("androidx.room3:room3-runtime:$room_version")
    ksp("androidx.room3:room3-compiler:$room_version")
}

গ্রুভি

dependencies {
    def room_version = "3.0.1"

    implementation "androidx.room3:room3-runtime:$room_version"

    ksp "androidx.room3:room3-compiler:$room_version"
}

প্রাথমিক উপাদান

রুমে তিনটি প্রধান উপাদান রয়েছে:

  • ডাটাবেস ক্লাস যা ডাটাবেস ধারণ করে এবং আপনার অ্যাপের সংরক্ষিত ডেটার সাথে অন্তর্নিহিত সংযোগের জন্য প্রধান অ্যাক্সেস পয়েন্ট হিসেবে কাজ করে।
  • ডেটা এনটিটিগুলো , যা আপনার অ্যাপের ডেটাবেসের টেবিলগুলোকে প্রতিনিধিত্ব করে।
  • ডেটা অ্যাক্সেস অবজেক্ট (DAO) হলো এমন ফাংশন যা ব্যবহার করে আপনার অ্যাপ ডাটাবেসে ডেটা কোয়েরি, আপডেট, ইনসার্ট এবং ডিলিট করতে পারে।

ডাটাবেস ক্লাসটি আপনার অ্যাপকে সেই ডাটাবেসের সাথে যুক্ত DAO-গুলোর ইনস্ট্যান্স সরবরাহ করে। এর ফলে, অ্যাপটি সংশ্লিষ্ট ডেটা এনটিটি অবজেক্টের ইনস্ট্যান্স হিসেবে ডাটাবেস থেকে ডেটা পুনরুদ্ধার করতে DAO-গুলো ব্যবহার করতে পারে। অ্যাপটি সংজ্ঞায়িত ডেটা এনটিটিগুলো ব্যবহার করে সংশ্লিষ্ট টেবিল থেকে সারি আপডেট করতে, অথবা সন্নিবেশের জন্য নতুন সারি তৈরি করতেও পারে। চিত্র ১-এ Room-এর বিভিন্ন উপাদানের মধ্যকার সম্পর্ক দেখানো হয়েছে।

চিত্র ১. কক্ষ গ্রন্থাগারের স্থাপত্য নকশা।

নমুনা বাস্তবায়ন

এই বিভাগে একটিমাত্র ডেটা এনটিটি এবং একটিমাত্র ডিএও (DAO) সহ একটি রুম (Room) ডেটাবেসের বাস্তবায়নের উদাহরণ উপস্থাপন করা হয়েছে।

ডেটা সত্তা

নিম্নলিখিত কোডটি একটি User ডেটা এনটিটি সংজ্ঞায়িত করে। User এর প্রতিটি ইনস্ট্যান্স অ্যাপের ডাটাবেসের একটি user টেবিলের একটি সারিকে প্রতিনিধিত্ব করে।

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String,
    @ColumnInfo(name = "last_name") val lastName: String
)

Room-এর ডেটা এনটিটি সম্পর্কে আরও জানতে, “Defining data using Room entities” দেখুন।

ডেটা অ্যাক্সেস অবজেক্ট (DAO)

নিম্নলিখিত কোডটি UserDao নামক একটি DAO সংজ্ঞায়িত করে। UserDao সেই ফাংশনগুলো সরবরাহ করে যা অ্যাপের বাকি অংশ user টেবিলের ডেটার সাথে ইন্টারঅ্যাক্ট করতে ব্যবহার করে।

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    suspend fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    suspend fun loadAllByIds(userIds: IntArray): List<User>

    @Query(
        """
        SELECT * FROM user
        WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1
        """
    )
    suspend fun findByName(first: String, last: String): User

    @Insert
    suspend fun insertAll(vararg users: User)

    @Delete
    suspend fun delete(user: User)
}

DAO সম্পর্কে আরও জানতে, ‘Room DAO ব্যবহার করে ডেটা অ্যাক্সেস করা’ দেখুন।

ডাটাবেস

নিম্নলিখিত কোডটি ডাটাবেস ধারণ করার জন্য একটি AppDatabase ক্লাস সংজ্ঞায়িত করে। AppDatabase ডাটাবেসের কনফিগারেশন নির্ধারণ করে এবং সংরক্ষিত ডেটাতে অ্যাপের প্রধান অ্যাক্সেস পয়েন্ট হিসেবে কাজ করে। ডাটাবেস ক্লাসটিকে অবশ্যই নিম্নলিখিত শর্তগুলো পূরণ করতে হবে:

  • ক্লাসটিকে অবশ্যই একটি @Database অ্যানোটেশন দিয়ে চিহ্নিত করতে হবে, যার মধ্যে একটি entities অ্যারে থাকবে এবং এই অ্যারেতে ডাটাবেসের সাথে যুক্ত সমস্ত ডেটা এনটিটি তালিকাভুক্ত থাকবে।
  • ক্লাসটি অবশ্যই একটি অ্যাবস্ট্রাক্ট ক্লাস হতে হবে যা RoomDatabase এক্সটেন্ড করে।
  • ডাটাবেসের সাথে যুক্ত প্রতিটি DAO ক্লাসের জন্য, ডাটাবেস ক্লাসকে অবশ্যই একটি অ্যাবস্ট্রাক্ট ফাংশন সংজ্ঞায়িত করতে হবে, যা কোনো আর্গুমেন্ট গ্রহণ করবে না এবং DAO ক্লাসের একটি ইনস্ট্যান্স রিটার্ন করবে।

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

দ্রষ্টব্য: যদি আপনার অ্যাপ একটি একক প্রসেসে চলে, তাহলে একটি AppDatabase অবজেক্ট ইনস্ট্যানশিয়েট করার সময় আপনার সিঙ্গেলটন ডিজাইন প্যাটার্ন অনুসরণ করা উচিত। প্রতিটি RoomDatabase ইনস্ট্যান্স বেশ ব্যয়বহুল, এবং একটি একক প্রসেসের মধ্যে আপনার একাধিক ইনস্ট্যান্সে অ্যাক্সেসের প্রয়োজন খুব কমই হয়।

আপনার অ্যাপ যদি একাধিক প্রসেসে চলে, তাহলে আপনার ডাটাবেস বিল্ডার ইনভোকেশনে enableMultiInstanceInvalidation() অন্তর্ভুক্ত করুন। এর ফলে, যখন প্রতিটি প্রসেসে AppDatabase এর একটি করে ইনস্ট্যান্স থাকবে, তখন আপনি একটি প্রসেসে শেয়ার করা ডাটাবেস ফাইলটিকে ইনভ্যালিডেট করতে পারবেন এবং এই ইনভ্যালিডেশনটি স্বয়ংক্রিয়ভাবে অন্যান্য প্রসেসের মধ্যে থাকা AppDatabase এর ইনস্ট্যান্সগুলোতেও ছড়িয়ে পড়বে।

ব্যবহার

ডেটা এনটিটি, ডিএও এবং ডেটাবেস অবজেক্ট সংজ্ঞায়িত করার পরে, আপনি ডেটাবেসের একটি ইনস্ট্যান্স তৈরি করতে নিম্নলিখিত কোডটি ব্যবহার করতে পারেন:

val db =
    Room.databaseBuilder<AppDatabase>(applicationContext, "database-name")
        .setDriver(AndroidSQLiteDriver())
        .build()

এরপর আপনি AppDatabase থেকে অ্যাবস্ট্রাক্ট ফাংশনগুলো ব্যবহার করে DAO-এর একটি ইনস্ট্যান্স পেতে পারেন। আবার, আপনি DAO ইনস্ট্যান্সের ফাংশনগুলো ব্যবহার করে ডাটাবেসের সাথে ইন্টারঅ্যাক্ট করতে পারেন:

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

অতিরিক্ত সম্পদ

Room সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত উৎসগুলো দেখুন:

নমুনা