Google အနေနဲ့ ၂၀၁၇ ခုနှစ်ထဲမှာ Android Developer တွေအတွက် အရေးပါတဲ့ Architecture Components တွေ ထုတ်ပေးခဲ့ပါတယ်။ ViewModel, LiveData, Room စတာတွေ ပါဝင်ပါတယ်။ Architecture Components ဆိုတဲ့အတိုင်း အားလုံးဟာ တစ်ခုနဲ့တစ်ခု ချိတ်ဆက်နေပါတယ်။
ဤပုံကို Google Architecture Components Guide မှ ရယူထားပါသည်။
အဲဒီ Android Architecture Component တွေထဲက တစ်ခုဖြစ်တဲ့ Room Persistence Library နဲ့ မိတ်ဆက်ပေးချင်ပါတယ်။
Room Persistence Library ဆိုတာ ဘာလဲ?
Room ဆိုတာ Android Local Data Store အနေနဲ့ အသုံးပြုတဲ့ SQLite အတွက် အလွယ်တကူ စီမံခန့်ခွဲနိုင်ဖို့ရာ အကူအညီပေးနိုင်တဲ့ Library တစ်ခုဖြစ်ပါတယ်။ ကျွန်တော်တို့ Android Developer တွေအနေနဲ့ စိတ်ပျက်စရာကောင်းတဲ့ အချက်တစ်ခုဖြစ်တဲ့ “Implementing from Start” အမြဲတမ်း အစကနေ ပြန်ပြန် တည်ဆောက်နေရတဲ့ ဒုက္ခကနေ လွတ်သွားအောင် အကူအညီပေးနိုင်ပါတယ်။ Realm ဆိုရင် Realm စတိုင်ပေါ့ (Realm အကြောင်းကို အောက်က ဆောင်းပါးနှစ်ပုဒ် မှာ လေ့လာနိုင်ပါတယ်။
အပေါ်က ပုံမှာ ပြထားတာက Realm Style ပါ။ Database Table တွေထဲကနေ အချက်အလက်တွေ ဆွဲထုတ်တဲ့အခါ နားလည်လွယ်တဲ့ Code တွေနဲ့ ရေးသား၊ ထုတ်ယူနိုင်ပါတယ်။
အပေါ်မှာ ပြထားတဲ့ ပုံမှာဆိုရင်လဲ Retrofit ရဲ့ ရိုးရှင်းနားလည်လွယ်တဲ့ အချက်အလက် ရယူမှု ပုံစံတွေကို မြင်တွေ့ရပါမယ်။ ဒါပေမယ့် SQLite ကို SQLite Open Helper နဲ့ ဖတ်မယ်ဆိုရင်တော့ အောက်မှာ ပြထားတဲ့အတိုင်း ရှုပ်ထွေးနေပါတယ်။
အဲဒီလို အကြိမ်ကြိမ် အထပ်ထပ် ရှုပ်ရှုပ်ထွေးထွေးတွေ ရေးနေရတာ အခုအချိန်မှာ မဖြစ်သင့်တော့ပါဘူး။ အဲဒီတော့ "တစ်ခြား SQLite ကို အသုံးပြုတဲ့ Third Party Library တွေကို အသုံးပြုမလား?" ဆိုပြန်တော့လည်း သုံးလို့ ရကောင်း၊ ရနိုင်ပါတယ်။ Google က တိုက်ရိုက် Support မဟုတ်တဲ့အတွက် တစ်ချိန်ချိန်မှာ Support ရပ်ဆိုင်းသွားတဲ့အခါ အခက်အခဲအများကြီး ရှိလာနိုင်ပါတယ်။
Room Persistence Library ကို ဘာကြောင့် ရွေးချယ်သင့်လဲ?
Room Persistence Library ကို အောက်ပါအချက်တွေကြောင့် ရွေးချယ်သင့်ပါတယ်။
- သုံးရလွယ်တယ်
- Google ရဲ့ ရေရှည် Support Library တစ်ခု ဖြစ်လာပါလိမ့်မယ်
- Android SQLite Database Implementation ကို အဆင့်တစ်ခုကနေ စနိုင်မယ်
- Content Provider နဲ့ တွဲသုံးလို့ရမယ်
- NoSQLတွေမှာ မရနိုင်တဲ့ Database Relationship တွေ, GroupBy စတာတွေ ရလာပါမယ်
- Auto Increment Value တွေ သုံးလို့ရပါမယ်
သုံးရလွယ်သွားတာတော့ အမှန်ပါပဲ။ အဲဒီအပြင် Google ရဲ့ ရေရှည် Support ပေးမယ့် Library တစ်ခု ဖြစ်လာပါလိမ့်မယ်။ Volley လို Library မျိုး ဖြစ်မသွားဖူးလို့လဲ ခန့်မှန်းရပါတယ်။
Google က ထုတ်ပေးလိုက်တဲ့ Library တိုင်း ရေရှည်ရပ်တည်နိုင်တာ မဟုတ်ပါဘူး။ Volley ဆိုရင် Retrofit ကို မယှဉ်နိုင်တဲ့အတွက် Google IO 2017 မှာ အသံတောင် မကြားရတော့ပါဘူး။
Room ကို အသုံးပြုလိုက်ခြင်းအားဖြင့် Android SQLite Database Implementation ကို ဟိုးအောက်ခြေ အစကနေ ပြန်ပြန်စနေစရာ မလိုတော့ပဲ Object Mapping အဆင့်ကနေ စနိုင်ပါတယ်။ ကျွန်တော်တို့ ဘယ် Database Library ကိုပဲ လေ့လာ၊ လေ့လာ အချက် (၃)ချက်နဲ့ ချဉ်းကပ်လို့ရပါတယ်။
- Low Level Implementation (လုံးဝ အခြေခံကစပြီး တည်ဆောက်ရတဲ့ ပုံစံ)
- Active Record ပုံစံ (Ruby on Rails မှာ အသုံးပြုတဲ့ ပုံစံ)
- Object Relation Mapper (ORM) ပုံစံ
ဆိုပြီး ရှိပါတယ်။ Room ဟာ ORM အထိလဲ မရောက်သေးသလို Active Record ပုံစံလဲ မဟုတ်တဲ့ Object Mapper ပုံစံနဲ့ ချဉ်းကပ်ထားပါတယ်။ (နောင်တစ်ချိန်မှာတော့ ORM အထိ ရောက်သွားမယ်လို့ မျှော်လင့်ရပါတယ်)။
ကျွန်တော်တို့ Android App ထဲက အချက်အလက်တွေကို အခြား App တွေနဲ့ ဝေမျှချင်တဲ့အခါ Content Provider ကို အသုံးပြုကြရပါတယ်။ အဲဒီလို Content Provider တွေ အသုံးပြုတဲ့အခါ "အလွယ်တကူ ပေါင်းစပ် အသုံးပြုနိုင်ရဲ့လား?" ဆိုတာ အင်မတန် အရေးကြီးပါတယ်။
ဥပမာ - Realm နဲ့ တွဲသုံးမယ်ဆိုရင် လွယ်လွယ်ကူကူ တွဲသုံးလို့ရ မရပါဘူး။ မဖြစ်ဖြစ်အောင် ရေးမယ်ဆိုရင် ရပေမယ့် SQLite တို့ Room တို့လောက် မလွယ်တော့ပါဘူး။
တစ်ခြား အားသာချက်တွေကတော့ NoSQL မှာ မရနိုင်တဲ့ Auto Increment Value တို့ Entity Relationship တို့ စတာတွေရလာပါမယ်။
ဒါပေမယ့် တစ်ခု သတိထားဖို့ လိုတာက Room အနေနဲ့ Realm လို NoSQL နဲ့ ယှဉ်မယ်ဆိုရင် Search လုပ်တဲ့နေရာမှာတော့ Realm ကို မှီမှာမဟုတ်ပါဘူး။ Realm က ပိုမြန်ပါတယ်။ (ကျွန်တော်ရဲ့ လက်တွေ့ စမ်းသပ်ချက်အရပါ)
Room မှာ ဘာတွေ ပါလဲ?
Room ကို စသုံးမယ်ဆိုရင် Room ရဲ့ အဓိက ပင်မအစိတ်အပိုင်း သုံးခုကို သိထားဖို့ လိုအပ်ပါတယ်။ အဲဒါတွေကတော့
- Room Entity
- Room DAO
- Room Database
တို့ပဲ ဖြစ်ပါတယ်။
Room Entity
Room Entity ဆိုတာကတော့ SQLite ထဲမှာ အမှန်တကယ် ရှိနေမယ့် Table နဲ့ Mapping ယူထားတဲ့ Class ဖြစ်ပါတယ်။ အဲဒီလို Mapping ယူထားတဲ့အတွက် Object Mapping လို့ ခေါ်ဝေါ် သုံးစွဲရခြင်း ဖြစ်ပါတယ်။ Object Mapping အပြင် Object Relational Mapping ဆိုရင်တော့ Table တွေကို Object Mapping ယူရုံတင် မကတော့ပဲ Table Relationship တွေကိုပါ Mapping ယူထားတာကို ဆိုလိုပါတယ်။
Room ကတော့ Object Mapping အဆင့်ပဲ ရှိပြီး Table Relationship တွေကိုတော့ Table တည်ဆောက်တဲ့နေရာမှာသာ အသုံးပြုနိုင်ပြီး အချက်အလက်များ ပြန်လည် ဖတ်ရှုရမှာတော့ အသုံးပြုလို့ ရမှာမဟုတ်ပါဘူး။ အဲဒီအတွက် SQL Language တွေ သုံးပြီး Table Relationship တွေကို ကိုယ်တိုင် ရေးညွှန်းပေးရမှာ ဖြစ်ပါတယ်။
အပေါ်မှာ ပြထားတဲ့ ပုံစံကတော့ Room Entity တစ်ခု တည်ဆောက်တဲ့ ပုံစံ ဖြစ်ပါတယ်။ Annotation အနေနဲ့
- PrimaryKey
- ForeignKey
- Index
- ColumnInfo
- Embedded
- Relation
- Ignore
ဆိုပြီး အသုံးပြုလို့ ရပါတယ်။
@PrimaryKey - ဆိုတာကတော့ ထုံးစံအတိုင်း SQL Database Table တွေမှာ Key အဖြစ် အသုံးပြုတာတွေကို သတ်မှတ်ပေးဖို့အတွက်ပါ။ @PrimaryKey(autoGenerate = true) လို့ ပေးထားရင်တော့ autoGenerated id တွေ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။
@ForeignKey - ဆိုတာကတော့ Table တစ်ခုနဲ့ တစ်ခု SQL သဘောတရားအရ One to Many, One to One စသည်ဖြင့် ချိတ်ဆက်နေတာတွေကို သတ်မှတ်ပေးဖို့အတွက် ဖြစ်ပါတယ်။
@Index - ဆိုတာကတော့ Database သဘောတရားအရ Index အဖြစ် မှတ်သား သိမ်းဆည်းချင်တဲ့ Column တွေကိ သတ်မှတ်ဖို့ ဖြစ်ပါတယ်။ သီးသန့် နမူနာပြရှင်းလင်းဖို့ ရှိပါတယ်။
@ColumnInfo - ဆိုတာကတော့ Database Table ထဲမှာ field column တွေရဲ့ အမည်တွေကို သတ်မှတ်ပေးချင်တဲ့ နေရာမှာ သုံးပါတယ်။ ဒီနေရာမှာ တစ်ခု သတိထားဖို့ လိုတာက In Memory Database အနေနဲ့ပဲ သုံးမယ်ဆိုရင်တော့ ColumnInfo တွေ မသတ်မှတ်ပေးလဲ သုံးလို့ရနိုင်ပါတယ်။
@Embedded - ဆိုတဲ့အပိုင်းကိုတော့ သီးသန့် ရှင်းပြထားတဲ့အတွက် ဒီနေရာမှာ မရှင်းပြတော့ပါဘူး။
@Relation - ဆိုတာကိုလဲ သီးသန့် ရှင်းပြထားပါတယ်။
@Ignore - ဆိုတာကတော့ Database ထဲမှာ မသိမ်းချင်တဲ့ Field တွေအတွက် လစ်လျူရှုနိုင်အောင် သတ်မှတ်ပေးတဲ့ နေရာမှာ သုံးပါတယ်။
Room DAO
Room DAO ကတော့ SQLite Database နဲ့ Interaction လုပ်ဖို့အတွက် သတ်မှတ်ပေးနိုင်တဲ့ Data Access Object ဖြစ်ပါတယ်။ Database ရဲ့ အဓိက အစိတ်အပိုင်းတွေ ဖြစ်တဲ့ CRUD တွေ ပြုလုပ်ပေးတဲ့ Object ဖြစ်ပါတယ်။
DAO ကို သတ်မှတ်တဲ့နေရာမှာ Interface အနေနဲ့ သတ်မှတ်ပေးရမှာ ဖြစ်ပြီး @Dao ဆိုတဲ့ Annotation ထည့်ပေးဖို့ လိုပါတယ်။ ဒီနေရာမှာ DAO ကို Table အားလုံးအတွက် တစ်ခုတည်း ပေါင်းရေးလို့ ရပေမယ့် အဲဒီလို မရေးသင့်ပါဘူး။ Table တစ်ခုကို DAO တစ်ခုအနေနဲ့ ခွဲခြား ရေးသားထားမှ နောက်တစ်ချိန်မှာ ပြန်ပြင်ရ လွယ်ပါမယ်။ Separation of Concerns ကိုလဲ လိုက်နာပြီး ဖြစ်ပါမယ်။
Object အတွင်းမှာတော့ Annotation အနေနဲ့ @Query, @Delete နဲ့ @Insert ဆိုပြီး သုံးမျိုး အသုံးပြုနိုင်ပါတယ်။ ဒီနေရာမှာ တစ်ခု သတိထားဖို့ လိုတာက Update အတွက် Annotation မပါတာပါ။ Update ပြုလုပ်ချင်တယ် ဆိုရင်တော့ @Query က တစ်ဆင့်ပဲ ပြုလုပ်နိုင်မှာပါ။ ပုံမှာ ပြထားတဲ့အတိုင်း နမူနာမှာကြည့်မယ်ဆိုရင် သိနိုင်ပါတယ်။
Room Database
Room Database ကတော့ Room Persistence Library ရဲ့ မင်းသားကြီး ဖြစ်ပါတယ်။
abstract class အနေနဲ့ အသုံးပြုရပြီး RoomDatabase ကို extend လုပ်ပေးဖို့ လိုအပ်ပါတယ်။ @Database ဆိုတဲ့ Annotation နဲ့အတူ entities တွေကို သတ်မှတ်ပေးဖို့ လိုအပ်ပါတယ်။ အဲဒီလို သတ်မှတ်ပေးမှသာ Table တွေ မရှိသေးရင် တည်ဆောက်မယ်။ Migrate လုပ်မယ်။ ရှိပြီးသားဆိုရင် မူရင်းအတိုင်း ဆက်လက် အသုံးပြုမယ်ဆိုတာတွေ သိနိုင်မှာ ဖြစ်ပါတယ်။ SQLite ကို SQL Open Helper အနေ သုံးဖူးတယ်ဆိုရင် ကျွန်တော်တို့အတွက် အဆင့်တွေ ဘယ်လောက်အထိ လျော့ချပေးတယ်ဆိုတာ သိနိုင်ပါတယ်။ ဒီ Class မှာ Database Migration တွေလဲ ပြုလုပ်ပေးနိုင်ပါတယ်။
အဲဒီအပြင် ကိုယ်အသုံးပြုမယ့် DAO တွေကိုလဲ သတ်မှတ်ပေးနိုင်ပါတယ်။ ပြီးရင်တော့ ကိုယ်သုံးချင်တဲ့ Singleton ကို သတ်မှတ်ပေးနိုင်ပါတယ်။
ဒီလို သတ်မှတ်ပေးတဲ့နေရာမျာ Object Singleton ပုံစံ သတ်မှတ်ပေးဖို့ လိုအပ်မှာ ဖြစ်ပါတယ်။ အဲဒီအပြင် In Memory Database နဲ့ ပုံမှန် သမာရိုးကျ Database ပုံစံလဲ သတ်မှတ်လို့ရပါတယ်။ အသုံးပြုချင်တဲ့အခါ Object ကို Singleton ပုံစံနဲ့ လှမ်းခေါ်ပြီး Activity Destory ဖြစ်တဲ့အချိန်မှာ Singlegon Object Instance ကို null ပြန်ပေးဖို့ လိုအပ်မှာ ဖြစ်ပါတယ်။
Room in Action
အဲဒီအဆင့်တွေ ပြီးသွားပြီဆိုရင်တော့ Room Persistance Library ကို ကိုယ့် Project မှာ သုံးလို့ရပါပြီ။
အဲဒီလို အသုံးပြုတဲ့နေရာမှာ UI Threat ထဲမှာ သုံးတာဖြစ်ဖြစ် Background Thread ထဲမှာ သုံးတာဖြစ်ဖြစ် ကြိုက်သလို အသုံးပြုနိုင်ပါတယ်။ ကျွန်တော်တို့ ရှေ့ဆက်ပြီး အခြား သိစရာရှိတဲ့ အကြောင်းအရာတွေ ရှေ့ဆက် လေ့လာကြည့်ရအောင် ...
Type Converter
TypeConverter ကတော့ အတော်လေး အသုံးဝင်တဲ့ Feature တစ်ခုဖြစ်ပါတယ်။ SQLite ထဲမှာ Date လို အချက်အလက်တွေ မှတ်သားသိမ်းဆည်းတဲ့အခါ Date Format နဲ့ သိမ်းလို့ မရပါဘူး။ long ပြောင်းပြီး သိမ်းဆည်းရပါတယ်။ အဲဒီလို အခြေအနေတွေအတွက် Type Converter က အများကြီး အသုံးဝင်ပါတယ်။ Entity, DAO, Database ကြိုက်တဲ့ နေရာမှာ သုံးလို့ရနိုင်ပါတယ်။
အပေါ်မှာ ပြထားတဲ့ TypeConverter သတ်မှတ်ပြီး Entity မှာ ဖြစ်ဖြစ် DAO မှာဖြစ်ဖြစ် Database မှာ ဖြစ်ဖြစ် @TypeConverters ဆိုတဲ့ Annotation နဲ့ သုံးလိုက်မယ်ဆိုရင် Date ကို long ပြောင်းပေးပြီး ပြန်ဖတ်တဲ့အခါ long ကို Date ပြန်ပြောင်းပေးပါလိမ့်မယ်။
Indices
Indices ဆိုတာကတော့ Database Field တွေထဲမှာ Index သတ်မှတ်ထားချင်တဲ့အခါ အသုံးပြုနိုင်ပါတယ်။
Index တစ်ခုတည်း သတ်မှတ်ချင်ရင် @Index ဆိုတဲ့ သတ်မှတ်ချက်နဲ့ သတ်မှတ်နိုင်ပြီး တစ်ခုထက် ပိုရင်တော့ indices ဆိုပြီး သတ်မှတ်ပေးနိုင်ပါတယ်။
Embedded
Embedded ဆိုတဲ့ Feature ကတော့ field တွေကို embedded ပြုလုပ်ပေးနိုင်တဲ့ ပုံစံဖြစ်ပါတယ်။
အထက်က ပုံကို လေ့လာကြည့်မယ်ဆိုရင် Address ဆိုတဲ့ Class တစ်ခု ရှိပါတယ်။ အဲဒီမှာ street, state, city နဲ့ post_code ဆိုပြီး ရှိပါတယ်။ အဲဒီ Address ကို User Class ထဲမှာ prefix “home_” နဲ့ prefix “office_”ဆိုပြီး @Embedded နဲ့ ပေးလိုက်တဲ့အခါ Database Table ထဲ ရောက်ရင် ပုံမှာ ပြထားတဲ့အတိုင်း Database field တွေ တည်ဆောက်သွားပါတယ်။
Relation
Relation ဆိုတာကတော့ Relationship ရှိနေတဲ့ Table တွေကို ချိတ်ဆက်ပေးနိုင်တဲ့ Feature တစ်ခုဖြစ်ပါတယ်။ SQL Query နဲ့ ချိတ်ဆက်ပြီး Query လုပ်နိုင်သလို @Relation ဆိုတဲ့ Annotation သုံးပြီးလဲ ချိတ်ဆက်နိုင်ပါတယ်။
ပုံမှာ ပြထားတာကို လေ့လာကြည့်မယ်ဆိုရင် Relation အသုံးပြုပုံကို သိနိုင်မယ် ထင်ပါတယ်။
Room Other Features
Room Persistence Library မှာ အခြား Feature တွေအနေနဲ့ Database Migration, Schemas Export နဲ့ LiveData နဲ့ အလွယ်တကူ ပေါင်းလို့ရတာတွေ ရှိပါသေးတယ်။ ရှေ့ဆက်လေ့လာချင်တယ်ဆိုရင်တော့ အောက်ကလင်ခ့်တွေမှာ လေ့လာနိုင်ပါတယ်။