آموزش Room در اندروید | کتابخانه Room چیست و چگونه کار می‌کند؟

دسته بندی: برنامه نویسی
سطح مقاله: متوسط
زمان مطالعه: 15 دقیقه
۲۴ شهریور ۱۳۹۹

اگر با برنامه نویسی اندروید آشنایی داشته باشید، احتمالاً نام کتابخانه Room به گوش‌تان خورده است. اگر بخواهید با دیتابیس در اندروید ارتباط برقرار کنید و با آن کار کنید، ما به شما کتابخانه Room را پیشنهاد می‌کنیم. شما در مقاله آموزش Room در اندروید، با کلیه عملیات CRUD و جزییات مربوط به استفاده از این کتابخانه شگفت انگیز در پروژه‌های خود آشنا می‌شوید. ما در طول این آموزش، یک برنامه برای ذخیره مخاطبان را ایجاد خواهیم کرد.

بهترین راه برای یادگیری که ما به شما پیشنهاد می‌کنیم این است که پروژه را کامل انجام دهید. ابتدا، یک پروژه جدید ایجاد کنید و کار با کتابخانه Room را همراه با مقاله آموزش Room در اندروید ما شروع کنید. در صورتی که در هر کجای این آموزش به مشکل برخورد کردید، می‌توانید از کد کامل این برنامه در Github استفاده کنید. در صورتی که با SQLite در اندروید آشنا نیستید، به شما پیشنهاد می‌کنیم درباره‌ی آن پیش از شروع این مقاله مطالعه کنید.

در تصویر زیر رابط کاربری (UI) برنامه به شما نشان داده شده است:

آموزش Room در اندروید

آموزش Room در اندروید

فهرست محتوای این مقاله

کتابخانه Room چیست؟

Room یک object relational mapper) ORM) برای پایگاه داده SQLite در اندروید و بخشی از کامپوننت‌های معماری است که توسط گوگل منتشر شده است. در هسته آن، تمامی کدهایی که در رابطه با Room می‌نویسید در نهایت به کد SQLite تبدیل می‌شوند. Room به شما این امکان را می‌دهد تا با سرعت بیشتری پایگاه داده را در اندروید ایجاد کرده و بتوانید با آن کار کنید. می‌توانید به Room به عنوان یک لایه انتزاعی بر روی پایگاه داده داخلی SQLite نگاه کنید.

راه اندازی یک پروژه جدید با Room

یک پروژه جدید در اندروید استودیو ایجاد کنید.
در فایل build.gradle سطح اپ، وابستگی‌های زیر را اضافه کنید.
dependencies {
  def room_version = "2.2.5"

  implementation "androidx.room:room-runtime:$room_version"
  annotationProcessor "androidx.room:room-compiler:$room_version"

در بخش repositories در فایل build.gradle سطح پروژه خود، اطمینان حاصل کنید که ()google  اضافه شده است.

repositories {
     google()
     jcenter()
}
اکنون پروژه را همگام سازی کنید.اکنون، پروژه شما آماده کار با Room است.

ایجاد اسکیما (Creating Schema)

در Room نیازی به نوشتن کلاس SQLiteOpenHelper یا نوشتن کوئری برای ایجاد جدول نیست. Room جداول را به طور خودکار برای شما ایجاد می‌کند. در Room ما یک کلاس POJO ساده تعریف کرده و آن را با [email protected] حاشیه نویسی (annotations) می‌کنیم.

در اینجا ما یک کلاس مدل برای مخاطب با تمامی حاشیه نویسی‌های مورد نیاز را ایجاد خواهیم کرد.

@Entity(tableName = "contact")
public class Contact {
    private String firstName;
    private String lastName;
    @PrimaryKey
    @NonNull
    private String phoneNumber;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @NonNull
    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(@NonNull String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

همان‌طور که می‌بینید، این یک کلاس ساده جاوا با حاشیه نویسی می‌باشد و دستورات پیچیده‌ای ندارد.

ما با حاشیه نویسی [email protected] یک جدول با نام سفارشی ایجاد کرده‌ایم. اگر نام یک جدول را ارائه ندهید، Room از نام کلاس به عنوان نام جدول استفاده می‌کند یعنی "Contact" (با C بزرگ).

وقتی یک کلاس را با [email protected] حاشیه نویسی می‌کنید، باید یک سازنده (constructor) بدون آرگومان ارائه دهید. در اینجا چون ما هیچ سازنده‌ای ارائه نداده‌ایم، java به طور خودکار سازنده پیش فرض (بدون آرگومان) را در زمان کامپایل وارد می‌کند.

اگر یک کلاس با [email protected] حاشیه نویسی شده باشد، باید یک کلید اصلی را با استفاده از حاشیه نویسی PrimaryKey مشخص کنید. در اینجا ما از phoneNumber به عنوان کلید اصلی استفاده می‌کنیم.

Room کلاس Contact ما را می‌گیرد و یک جدول با فیلدهای ارائه شده به عنوان ستون ایجاد می‌کند.

اگر در شرایطی نمی‌خواهید فیلدی در طرح جدول در نظر گرفته شود، فقط آن را با [email protected] حاشیه نویسی کنید.

به طور پیش‌فرض در Room از نام فیلدها استفاده می‌شود، فیلدها نام ستون‌ها در جداول هستند، اما می‌توانید با استفاده از حاشیه نویسی ("ColumnInfo (name = "[email protected] در قسمت هر فیلد، این مورد را تغییر دهید.

ایجاد data access object) DAO) 

اکنون ما یک DAO برای انجام عملیات در جدول خود ایجاد خواهیم کرد. می‌توانید نگاهی عمیق به مفهوم DAO بیندازید، به طور خلاصه DAO فقط یک کلاس انتزاعی است که مجموعه‌ای از عملیات مربوط به یک شی را تعریف می‌کند.

در زیر یک interface) DAO) ساده با عملگر CRUD در Contact آورده شده است.

@Dao
public interface ContactDAO {
    @Insert
    public void insert(Contact... contacts);

    @Update
    public void update(Contact... contacts);

    @Delete
    public void delete(Contact contact);
}

برای ایجاد DAO، باید یک اینترفیس ایجاد کنید و آن را با Dao حاشیه نویسی کنید.

عملیات اضافه کردن (Insert)

برای ایجاد یک عملیات درج یا اضافه کردن، فقط متدی را تعریف کنید که (Contact contacts) را به عنوان یک پارامتر بگیرید و متد را با [email protected] حاشیه نویسی کنید.

عملیات بروزرسانی (Update)

مشابه با همان کاری که برای عملیات اضافه کردن انجام دادید، برای ایجاد یک عملیات بروزرسانی، فقط متدی را تعریف کنید که (Contact contacts) را به عنوان یک پارامتر بگیرید و متد را با [email protected] حاشیه نویسی کنید.

عملیات پاک کردن (Delete)

مانند کارهای قبلی، برای ایجاد یک عملیات پاک کردن، فقط متدی را تعریف کنید که (Contact contacts) را به عنوان یک پارامتر بگیرید و متد را با [email protected] حاشیه نویسی کنید.

کار با کوئری‌ها

در حالی که Room دارای حاشیه نویسی برای عملیات ساده در پایگاه داده است، اما همچنین امکان سفارشی سازی کوئری‌های نوشته شده را نیز فراهم می‌کند. بنابراین اگر می‌خواستید تمام مخاطبین را به دست آورید، یک کوئری مانند زیر می‌نویسید.

@Query("SELECT * FROM contact")
public List<Contact> getContacts();

از حاشیه نویسی [email protected] استفاده کنید و کوئری مورد نظرتان را اجرا کنید. از آنجا که ما تمام مخاطبین موجود در جدول را می‌خواهیم، نوع بازگشتی به لیست مخاطبین را، <List<Contact تنظیم می‌کنیم. Room همه این کارها را در پشت صحنه انجام می‌دهد، Room، کوئری را اجرا می‌کند، نتیجه مکان نما را به لیست تبدیل می‌کند و لیست را به شما باز می‌گرداند.

حال فرض کنید می‌خواهید برای به دست آوردن اطلاعات تماس مرتبط با یک شماره تلفن خاص، کوئری بنویسید. در اینجا نحوه نوشتن این متد و کوئری آورده شده است:

@Query("SELECT * FROM contact WHERE phoneNumber = :number")
public Contact getContactWithId(String number);

phoneNumber را در آرگومان‌های متد منتقل کرده و با پیشوند نام پارامتر با : (دونقطه) از آن در داخل کوئری استفاده کنید. نوع بازگشتی در اینجا Contact است زیرا ما به دنبال یک contact هستیم.

در زیر کد کامل اینترفیسDAO آورده شده است:
@Dao
public interface ContactDAO {
    @Insert
    public void insert(Contact... contacts);

    @Update
    public void update(Contact... contacts);

    @Delete
    public void delete(Contact contact);

    @Query("SELECT * FROM contact")
    public List<Contact> getContacts();

    @Query("SELECT * FROM contact WHERE phoneNumber = :number")
    public Contact getContactWithId(String number);
}

Room از این اینترفیس استفاده می‌کند و تمامی متدها را برای شما پیاده سازی می‌کند، تنها کاری که شما باید انجام دهید این است که عملیات را با استفاده از حاشیه نویسی مناسب مشخص کنید.

ایجاد پایگاه داده

حال تنها کاری که ما باید انجام دهیم این است که تمام کلاس‌ها و اینترفیس‌های فوق را به هم ارتباط دهیم. برای این منظور ما یک کلاس انتزاعی به نام AppDatabase ایجاد خواهیم کرد که RoomDatabase را گسترش می‌دهد. این کلاسی خواهد بود که به ما امکان پیاده سازی رابط DAO را می‌دهد.
@Database(entities = {Contact.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract ContactDAO getContactDAO();
}

شما باید این کلاس انتزاعی را با [email protected] حاشیه نویسی کنید و تمام موجودیت‌هایی را که ایجاد کرده‌اید و همچنین نسخه پایگاه داده را مشخص کنید.

شما یک متد انتزاعی با نوع بازگشت ContactDAO مشخص خواهید کرد. Room با اجرای کامل این کلاس انتزاعی همراه با همه متد‌های انتزاعی مشخص، به ما امکان توسعه می‌دهد.

اکنون هر کجا که نمونه‌ای از AppDatabase را می‌خواهید، کد زیر را بنویسید.

AppDatabase database = Room.databaseBuilder(this, AppDatabase.class, "db-contacts")
                .allowMainThreadQueries()   //Allows room to do operation on main thread
                .build()
()Room.databaseBuilder سه آرگومان را می‌گیرد:
  1. ارجاعی به Context که در این مثال از this استفاده شده.
  2.  استفاده از کلاس پایگاه داده انتزاعی برای بازگرداندن نمونه.
  3. نام پایگاه داده.

می‌توانید مشاهده کنید که ما یک متد ()allowMainThreadQueries را روی سازنده (Builder) فراخوانی کرده‌ایم، زیرا به طور پیش فرض Room به شما اجازه نمی‌دهد کوئری‌ها را در MainThread اجرا کنید و مجبورید آن‌ها را روی یک Background Thread اجرا کنید.

بنابراین ما از روش ()allowMainThreadQueries ارائه شده توسط Room استفاده می‌کنیم که به شما اجازه می‌دهد تا نمایش داده‌ها در MainThread اجرا شوند.

پس از دریافت نمونه AppDatabase، اکنون می‌توانید ContactDAO را با فراخوانی ()getContactDAO که قبلاً تعریف کرده‌اید دریافت کنید و فراخوانی متد‌های CRUD تعریف شده را شروع کنید.

ContactDAO contactDAO = database.getContactDAO();

//Inserting a contact
Contact contact = new Contact();
contact.setFirstName("Gurleen");
contact.setLastName("Sethi");
contact.setPhoneNumber("1234567890");

contactDAO.insert(contact);

//Fetching all contacts
List<Contact> contact = contactDAO.getContacts();

//Getting a single contact and updating it
Contact contact = contactDAO.getContactWithId("1234567890");

contact.setFirstName("Kevin");
contact.setLastName("Brew");

contactDAO.update(contact);

ذخیره انواع غیر ابتدایی جاوا (non-primitive types) با استفاده از Type Converters

در Room فقط می‌توانید انواع ابتدایی (primitive) زبان را ذخیره کنید. اگر می‌خواهید یک نوع غیر ابتدایی مانند یک لیست یا تاریخ را ذخیره کنید، باید یک نوع مبدل برای آن تهیه کنید. با TypeConverter به Room می‌گویید که چگونه نوع غیر اولیه را به نوع اولیه تبدیل کند. ما یک فیلد تاریخ ایجاد شده از نوع Date را در مدل Contact خود اضافه خواهیم کرد.
@Entity(tableName = "contact")
public class Contact {
    private String firstName;
    private String lastName;
    @PrimaryKey
    @NonNull
    private String phoneNumber;
    private Date createdDate;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @NonNull
    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(@NonNull String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }
}
اگر سعی کنید این کد را بدون ارائه مبدل نوع اجرا کنید، Room هنگام کامپایل خطا می‌دهد.
در این پروژه ما مبدل را برای نوع Date فراهم خواهیم کرد‌ و تاریخ را به long تبدیل خواهیم کرد. هنگام نوشتن مبدل، شما باید هر دو روش را ارائه دهید، در این پروژه یعنی، یک مبدل که Date را به Long تبدیل می‌کند و دیگری که Long را به Date تبدیل می‌کند.
public class DateTypeConverter {
    @TypeConverter
    public long convertDateToLong(Date date) {
        return date.getTime();
    }

    @TypeConverter
    public Date convertLongToDate(long time) {
        return new Date(time);
    }
}

می‌بینید که ما یک کلاس جدید به نام DateTypeConverter با متدهای مورد نیاز ایجاد کرده‌ایم. حال باید به Room بگوییم که از این نوع مبدل استفاده کند. در کلاس AppDatabase ما باید بگوییم که از کدام نوع مبدل استفاده کنیم. این کار را با استفاده از حاشیه نویسی [email protected] انجام می‌دهیم.

@Database(entities = {Contact.class}, version = 1)
@TypeConverters({DateTypeConverter.class})
public abstract class AppDatabase extends RoomDatabase {
    public abstract ContactDAO getContactDAO();
}
اکنون می‌توانید بدون هیچ مشکلی برنامه را اجرا کنید.

جمع‌بندی:

در این مقاله ما با آموزش Room در اندروید و ویژگی‌های آن همراه شما بودیم، ما بهترین راه برای یادگیری کتابخانه Room را پیشنهاد کردیم و امیدواریم از این راه بتوانید کتابخانه Room را فرا گرفته و با آن کار کنید. خوشحال می‌شویم سوالات و نظرات خود را در مورد این آموزش با ما و کاربران سون لرن به اشتراک بگذارید.

اگر به یادگیری بیشتر در زمینه‌ی اندروید علاقه داری، با شرکت در دوره‌ی آموزشی متخصص اندروید در کمتر از یکسال به یک توسعه‌دهنده اندروید همه فن حریف تبدیل می‌شوی که آماده‌ی استخدام، دریافت پروژه و حتی پیاده‌سازی اپلیکیشن خودت هستی.

چه امتیازی به این مقاله می دید؟

نظرات کاربران

اولین دیدگاه این پست رو تو بنویس !

ارسال دیدگاه
خوشحال میشیم دیدگاه و یا تجربیات خودتون رو با ما در میون بذارید :