استفاده از دیتابیس Room در سورس اندروید

فوریه 18, 2019| سنا عبادی
استفاده از دیتابیس ROOM در سورس اندروید خود | اندروید ریور

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

دیتابیس در اندروید یکی از مهمترین و تخصصی ترین بحث هایی هست که در هر سورس اندروید  مورد استفاده قرار میگیرند.

نحوه پیاده سازی دیتابیس Room در سورس اندروید

یکی از این ORM های معروف که پشتیبانی گوگل را به همراه دارد ROOM است که در سال ۲۰۱۸ گوگل آن را در مجموعه ی کامپوننت هایی که به نام JetPack بود قرار داد . زیرا که یکی از بهترین کامپوننت ها به شمار می آمد.

ساختار کلی استفاده از دیتابیس Room مانند شکل مقابل است که با توضیح مختصر ادامه خواهیم داد :

Entity : یکی از انوتیشن های Room است که در کلاس ساخت جدول برای دیتابیس استفاده می شود.

SQLite database‌: اطلاعات اپلیکشن شما در هر دیوایسی در دیتابیس مورد نظر ذخیره خواهند شد . Room این فرایند ذخیره سازی را به کمک sqlite راحت کرده است و انجام میدهد.

DAO : مخفف عبارت Data access object است . تمامی کویری هایی که برای دیتابیس باید استفاده کنید باید در این کلاس فراخوانی شوند. کویری هایی مانند @Delete , @Insert ,Update

Room database : بلاترین سطح SQLite database که برای مدیریت با SQLiteOpenHelper است .که به کمک کلاس DAO تمامی کویری ها را مدیریت و پردازش می کند.

Repository : کلاسی هست که توسط خود شما ساخته می شود که وظیفه ی ذخیره سازی منابع هست که به مانند پل ارتباطی بین مدل و دیتابیس است .

ViewModel : کلاس مدلی که پل ارتباطی بین UI و Repository هست.تمامی المنت هایی که در UI برای دیتابیس مورد استفاده هستند به راحتی با ریپوزیتوری دیتابیس در تعامل خواهند بود که در این جا به راحتی می توان از LiveData استفاده کرد.

LiveData : لایو دیتا به کمک observed تمامی دیتا را در اخرین state ذخیره می کند و هنگام تغییرات تمامی دیتا سریعا آپدیت می شود.این کامپونتت از LifeCycle پشتیبانی می کند.لایو دیتا به صورت اتوماتیک تمامی تغییرات ui را در لحظه آپدیت می کند.

گام اول : آپدیت فایل گریدل

برای استفاده از Room باید تغییرات زیر را در فایل build.gradle خود اعمال کنید :


def room_version = "2.1.0-alpha04"
def lifecycle_version = "2.0.0"

//lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
testImplementation "androidx.arch.core:core-testing:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"

//Room
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
testImplementation "androidx.room:room-testing:$room_version"

نکته : برای اینکه شما تنها بکبار ورژن را در فایل بیلد گریدل برای چند کامپوننت هم ورژن و از یک دپندنسی داشته باشید آن را در قسمت بالا و قبل از تمامی دپندنسی ها و در بلاک dependencies به صورت گلوبال تعریف کنید.

نکته : در این مقاله از کتابخانه های androidx ‌استفاده شده است.

گام دوم : ساخت کلاس entity 

در این کلاس شما باید تیبل (جدول) دیتابیس خود را ایجاد کنید و هم چنین ستون های مورد نیاز خود را تشکیل دهید .و هم چنین کانسراکتور های مورد نیاز را فراخوانی کنید . و getter برای فیلد های این کلاس نیز مورد نیاز خواهد بود.
فرض کنید نام کلاس ما Word باشد پس طبق کد زیر باید تیبل و ستون هایش را بسازید :

@Entity(tableName = "word_table")
public class Word {

@PrimaryKey
@NonNull
@ColumnInfo(name = "word")
private String mWord;

@PrimaryKey(autoGenerate = true)
private int id;

public Word(String word) {this.mWord = word;}

public String getWord(){return this.mWord;}
}

به صورت مختصر برای هر قسمت از این کد تعریفی خاهیم داشت :
@Entity(tableName = “word_table”) : Entity برای ساخت جدول پایگاه داده شما است و در آن آرگومانی به شکل tableName که مقدار STRING را میپذیرد را باید تعریف کرد که همان نام جدول ما خواهد بود.

@PrimaryKey : هر جدولی به این کلید نیاز دارد.که برای ستون منحصر به فردی مانند ID ب کار میرود.

@PrimaryKey(autoGenerate = true)
private int id;

@NonNull : هنگامی که از این انوتیشن استفاده میکنیم قرار هست که آن متد یا فیلد و پارامتری که داریم هرگز مقدار NULL را نپذیرد.

همچنین بخوانید :  معرفی دیتابیس برای برنامه نویسی اندروید

@ColumnInfo(name = “word”) : این قسمت برای تعریف نام ستون است . شما میتوانید n تا ستون داشته باشید که برای اینکه شما نام ستون خود را با متغیری که در جاوا تعریف کنید متفاوت باشد استفاده میکنید .به طور مثال نام ستون شما word هست ولی برای این ستون متغیری به اسم mWord در نظر گرفته اید . به همین خاطر از این انوتیشن استفاده می کنید.

getWord() : هنگامی که شما متغیر ها را به صورت private تعریف می کنید ولی قرار است از آنها در کلاس های دیگر استفاده کنید باید برای آنها متد getter /setter فراخوانی کنید که در این مثال فقط از getter استفاده می کنیم .

نکته : به قسمت import های مربوط به کلاس توجه کنید . باید به صورت زیر باشند :

import android.arch.persistence.room.ColumnInfo;

import android.arch.persistence.room.Entity;

import android.arch.persistence.room.PrimaryKey;

import android.support.annotation.NonNull;

برای اطلاعات بیشتر برای ایجاد کلاس Entity به لینک اصلی داکیومنت های خود گوگل مراجعه کنید.

گام سوم : ایجاد DAO
تمامی کویری های sql در این فایل که باید interface یا abstract class باشد , قرار می گیرند.

به کد زیر توجه کنید :


@Dao
public interface WordDao {

@Insert
void insert(Word word);

@Query("DELETE FROM word_table")
void deleteAll();

@Query("SELECT * from word_table ORDER BY word ASC")
List getAllWords();
}

۱.اینترفیسی به اسم WordDao ایجاد کنید.
۲.با قرار دادن انوتیشن @Dao در بالای این اینترفیس , فایل مورد نظر را به عنوان Dao به Room معرفی کنید.
۳.متد void insert(Word word); را برای تزریق دیتا به دیتابیس استفاده کنید . که باید انوتیشن @Insert را حتما در بالای این متد قرار دهید .
۴.متد void deleteAll();. برای حذف کل دیتا از دیتابیس است که با انوتیشن @Query اینکار انجام پذیر است.@Query(“DELETE FROM word_table”) این کویری تمامی دیتا را به صورت یکجا از دیتابیس پاک میکند.
۵.متد getAllWords(); که آرایه ایی از کلاس word را بر میگرداند.به این صورت List getAllWords();. که کویری @Query(“SELECT * from word_table ORDER BY word ASC”) را باید استفاده کنید.

نکته : در این کلاس برای گرفتن دیتا می توان از liveData استفاده کرد . که با توجه به مزیت هایی که توضیح دادیم باعث سینک شدن و هماهنگی تغییرات ui و دیتابیس خواهد شد.
یعنی کد به این صورت تغییر خواهد کرد :


@Query("SELECT * from word_table ORDER BY word ASC")
LiveData<List> getAllWords();

برای اطلاعات بیشتر از dao ‌به داکیومنت اصلی مراجعه کنید.

گام چهارم : ایجاد کلاس Room database

توضیحات مختصر مربوط به این کلاس را کمی پیش قرار دادیم پس سراغ ساخت این کلاس رویم :
۱.کلاسی را با شرط public abstract که از RoomDatabase مشتق می شود را به نام WordRoomDatabase ایجاد کنید.

 
public abstract class WordRoomDatabase extends RoomDatabase {}

۲.با قرار دادن انوتیشن @Database باید این کلاس را ب عنوان کلاس دیتابیس معرفی کنیم .

 

@Database(entities = {Word.class}, version = 1)

که باید کلاس Entity (word ) که در آن تیبل را ساختیم معرفی کنیم و نیز ورژن دیتابیس را مشخص کنیم که با هر تغییر این ورژن تغییر میکند.
۳. برای dao متدی به صورت public abstract WordDao wordDao(); تعریف کنید .

 

در کل کدی ب این صورت خواهید داشت :

@Database(entities = {Word.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {
public abstract WordDao wordDao();

}

۴. کلاس WordRoomDatabase را Singleton کنید . به این صورت که یکبار تعریف کنید و در سورس از آن استفاده کنید.
یعنی کدی به این صورت بنویسید :


private static volatile WordRoomDatabase INSTANCE;

static WordRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (WordRoomDatabase.class) {
if (INSTANCE == null) {
// Create database here
}
}
}
return INSTANCE;
}

 

که با توجه به نام کلاس هاتون باید تغییرات را ایجاد کنید .

۵ . برای اینکه دیتابیس را بسازید باید کد زیر را تعریف کنید :


// Create database here
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.build();

در کل باید کد کامل این کلاس به این شکل باشد :


@Database(entities = {Word.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {

public abstract WordDao wordDao();

private static volatile WordRoomDatabase INSTANCE;

static WordRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (WordRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.build();
}
}
}
return INSTANCE;
}
}

نکته : اگر در بیلد کد ها و یا کلاس های مربوط به Room با مشکل مواجه شدید حتما از منوی Build یکبار پروژه را make ‌و اگر همچنان مشکل پا برجا بود از Rebuild / Clean استفاده کنید.

گام پنجم : ایجاد Repository 

همچنین بخوانید :  افزودن Firebase Crashlytics به سورس اندروید

اگر به تصویر زیر دقت کنید هدف از ایجاد این کلاس را متوجه خواهید شد :

این کلاس تمامی کویری ها را به کمک Thread ها چندین عمل را در بک گراند انجام میدهد به همین خاطر از این کلاس استفاده میکنیم .
۱.کلاسی با عنوانWordRepository ایجاد کنید.
۲.از dao خود متغیری را تعریف کنید و نیز لیستی از کلاس word خود به کمک LiveData ایجاد کنید :


private WordDao mWordDao;
private LiveData<List> mAllWords;

۳.کانسراکتوری برای تعریف کلاس دیتابیس و نیز متغیر dao و نیز لیست کلاس word خود قرار دهید .

WordRepository(Application application) {
WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
mWordDao = db.wordDao();
mAllWords = mWordDao.getAllWords();
}

۴.متدی برای گرفتن لیست کلاس word به کمک liveData تعریف کنید :

LiveData<List> getAllWords() {
return mAllWords;
}

۵.برای insert باید متدی که که به کمک AsyncTask ایجاد کرده ایم را در non-UI thread تعریف کنیم در غیر اینصورت اپ شما کرش میکند.

public void insert (Word word) {
new insertAsyncTask(mWordDao).execute(word);
}

۶. کدی که از کلاس AsyncTask برای insert و یا delete دیتا استفاده میکند را به شکل زیر تعریف کنید :

private static class insertAsyncTask extends AsyncTask<Word, Void, Void> {

private WordDao mAsyncTaskDao;

insertAsyncTask(WordDao dao) {
mAsyncTaskDao = dao;
}

@Override
protected Void doInBackground(final Word... params) {
mAsyncTaskDao.insert(params[0]);
return null;
}
}

تنها با تغییرات جزیی در کد فوق شما می توانید از آن تنها با کپی کردن استفاده کنید.

در آخر کد کامل این کلاس به این صورت خواهد بود :

 

public class WordRepository {

private WordDao mWordDao;
private LiveData<List> mAllWords;

WordRepository(Application application) {
WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
mWordDao = db.wordDao();
mAllWords = mWordDao.getAllWords();
}

LiveData<List> getAllWords() {
return mAllWords;
}

public void insert (Word word) {
new insertAsyncTask(mWordDao).execute(word);
}

private static class insertAsyncTask extends AsyncTask<Word, Void, Void> {

private WordDao mAsyncTaskDao;

insertAsyncTask(WordDao dao) {
mAsyncTaskDao = dao;
}

@Override
protected Void doInBackground(final Word... params) {
mAsyncTaskDao.insert(params[0]);
return null;
}
}
}

گام ششم :ایجاد کلاس ViewModel

این کلاس رابط بین UI و ریپوزیتوری است . viewModel جزیی از کامپوننت lifeCycle است .
برای اینکه Ui از اکتیویتی و فرگمنت به صورت جداگانه رفتار کند از این کلاس استفاده خواهیم کرد.

۱.کلاسی به نام WordViewModel که از AndroidViewModelمشتق می شود را ایجاد کنید :

 
public class WordViewModel extends AndroidViewModel {}

۲.از کلاس WordRepository نمونه ایی را ایجاد کنید :

 
private WordRepository mRepository;

۳.برای گرفتن لیست word به کمک liveData متدی به این صورت تعریف کنید :

 
private LiveData<List> mAllWords;

۴.کانسراکتوری برای مقدار دهی ریپوزیتوری و نیز لیست دیتا تعریف کنید :

 
public WordViewModel (Application application) {
super(application);
mRepository = new WordRepository(application);
mAllWords = mRepository.getAllWords();
}

۵.برای words ‌متد getter را صدا بزنید :

 
LiveData<List> getAllWords() { return mAllWords; }

۶.برای insert کردن دیتا مدلی به این صورت تعریف کنید :

 
public void insert(Word word) { mRepository.insert(word); }

در آخر باید کد کاملی به این صورت داشته باشید :

 
public class WordViewModel extends AndroidViewModel {

private WordRepository mRepository;

private LiveData<List> mAllWords;

public WordViewModel (Application application) {
super(application);
mRepository = new WordRepository(application);
mAllWords = mRepository.getAllWords();
}

LiveData<List> getAllWords() { return mAllWords; }

public void insert(Word word) { mRepository.insert(word); }
}

نکته : برای delete نیز می توانید متدی همچون insert ایجاد کنید.

برای اطلاعات بیشتر راجب به ViewModel به این ویدیو از خود داکیومنت گوگل مراجعه کنید.

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

  خرید سورس های حرفه ای بازی و اپلیکیشن اندروید

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

دسته‌ها: معرفی سرویس ها و ابزار ها

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *