為什么我不再使用Realm

也許你并沒有聽說過 Realm 掏婶,這是一個面向安卓(亦面向iOS)的移動端數(shù)據(jù)庫技術(shù)管怠。和SQLite不同棍现,它允許你在持久層直接和數(shù)據(jù)對象工作淮椰。在它之上是一個函數(shù)式風(fēng)格的查詢api臼寄,眾多的努力讓它比傳統(tǒng)的SQLite 操作更快 霸奕。基于這些原因讓我決定試試Realm 吉拳。

大約一年前质帅,當(dāng)我第一次使用Realm 的時候,給我的第一印象非常不錯留攒。我需要保持一些用戶數(shù)據(jù)在手機(jī)本地煤惩,但是SharedPreferences用起來有點(diǎn)復(fù)雜了。Realm允許我用快速干凈的代碼里完成這件事情炼邀。它完全不需要像SQLite那樣自己手動寫額外的代碼魄揉。

我接下來的一個項(xiàng)目在缺少網(wǎng)絡(luò)連接的時候需要一個比較復(fù)雜的離線模式。從網(wǎng)絡(luò)抓取的數(shù)據(jù)必須保存在手機(jī)本地拭宁。我決定完全使用Realm 并觀察它隨項(xiàng)目增大是如何擴(kuò)大的洛退。

而我很快發(fā)現(xiàn)Realm讓數(shù)據(jù)模型的工作成了一種負(fù)擔(dān)瓣俯。它有幾個限制以至于我必須在整個代碼基礎(chǔ)上做處理。結(jié)果我嘗試在Realm之上抽象出另外一層來減輕這種限制兵怯。

定義對象

為了說明這些限制彩匕,讓我們從簡單的Person對象開始:

public class Person extends RealmObject {  
    private String name;  
    private int age;    
    public String getName() { return name; }  
    public void setName(String name) { this.name = name; }    
    public int getAge() { return age; }  
    public void setAge(int age) { this.age = age; }
}

注意我們必須直接繼承自RealmObject。這阻礙我們利用數(shù)據(jù)模型中的任意類型的繼承媒区。

并且我們還不能定義除setters 和 getters之外的實(shí)例方法驼仪。如果你想重寫equals 或者toString那么你就別想了。這樣導(dǎo)致的另外一個后果就是我們只能局限于使用標(biāo)記接口模式(marker interfaces) (注解也是可以的 )袜漩。

不僅僅被限制于setters 和 getters绪爸,實(shí)際上我們還必須提供它們。因此我們的數(shù)據(jù)對象是不可變的宙攻!另外奠货,setters 和 getters方法只是為Realm替換自己實(shí)現(xiàn)的代理方法。它不能操作數(shù)據(jù)座掘,跑出異常仇味,或者打印日志。

雖然我們可以提供一個非默認(rèn)的構(gòu)造函數(shù)雹顺,但是我們必須保證存在一個空的構(gòu)造函數(shù)丹墨。如果你想用一個builder 或者工廠方法來作為實(shí)例化的唯一途徑,那么這種限制就成了一個問題嬉愧。稍后我們將看看如何用Realm創(chuàng)建對象贩挣。

在我們能持有的field類型方面,也有一些限制没酣。所有的基本數(shù)據(jù)類型以及它們的封裝類型都能支持王财,包括String, Date, 和byte[]`。但是對于其它類型裕便,為了被持久化绒净,必須繼承自RealmObject。Lists可以用RealmList來支持偿衰。

但是也僅此而已挂疆。如果我們想使用枚舉而不是int,是沒有辦法的(找到一個使用@IntDef的理由了)下翎。我們還不能使用集合類型缤言,比如Set和Map。

創(chuàng)建和更新對象

為了創(chuàng)建一個Person類的實(shí)例视事,我們必須做如下事情:

Realm realm = Realm.getInstance(context);
realm.beginTransaction();
Person person = realm.createObject(Person.class);
person.setName("John");
person.setAge(25);
realm.commitTransaction();

你會注意到我們必須包裹一下Person 對象胆萧,同時任何對它的修改都在一個transaction 中。如果我們能在transaction 之外做這件事情并在我們準(zhǔn)備好的時候持久化它俐东,就要靈活得多跌穗。而現(xiàn)在我們在想要創(chuàng)建或者更新我們對象的任何時候都要卡在寫額外的Realm 代碼上面订晌。

之前我提過我們可以定義一個非默認(rèn)的構(gòu)造函數(shù)。比如蚌吸,對于Person我們可能有一個帶有name 和 age的構(gòu)造函數(shù):

public class Person extends RealmObject {  
    private String name;  
    private int age;    
    public Person(String name, int age) {    
        this.name = name;    
        this.age = age;  
    }    
    public Person() {    
        // required empty public constructor  
    }    
    // setters and getters  
    ...
}

我們不再需要直接調(diào)用setters :

Person person = new Person("John", 25);
realm.beginTransaction();
Person realmPerson = realm.copyToRealm(person);
realm.commitTransaction();

這讓我們省去了一些寫額外代碼的時間腾仅,但是仍然受限于transaction。

Mitigating These Issues

為了避免在基礎(chǔ)代碼中處理這些限制套利,我為數(shù)據(jù)對象定義了兩套類: POJOs (普通對象)和Realm 對象。然后我們創(chuàng)建了一個能在兩者之間映射的abstraction 鹤耍。

這是可行的肉迫,但是有兩個主要的問題。第一個是當(dāng)你持有許多不同類型的對象時稿黄,你需要許多代碼來映射這些類喊衫。管理這些是很痛苦的而且這也很容易產(chǎn)生bug。 對象映射的概念以及它存在的問題都不是什么新東西了杆怕。

第二個就是我覺得這有違最初使用Realm的目的族购。能在持久層直接使用對象是它的主要好處。如果我們?yōu)榱耸褂肞OJO而必須在Realm 之上創(chuàng)建抽象陵珍,那么它相比SQLite或者像 DBFlow一樣的ORM的優(yōu)勢在哪里呢寝杖?

值得一提的是Realm 的維護(hù)者已經(jīng) 意識到了這些限制 ,而且在一定程度上互纯,許多問題都可能被解決(見這里這里))瑟幕。Realm也的確具有一些其它的優(yōu)勢,比如性能以及在iOS和安卓之間共享數(shù)據(jù)的能力留潦。

英文原文:Why I Don't Use Realm Anymore

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末只盹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子兔院,更是在濱河造成了極大的恐慌殖卑,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坊萝,死亡現(xiàn)場離奇詭異孵稽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)十偶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門肛冶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扯键,你說我怎么就攤上這事睦袖。” “怎么了荣刑?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵馅笙,是天一觀的道長伦乔。 經(jīng)常有香客問我,道長董习,這世上最難降的妖魔是什么烈和? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮皿淋,結(jié)果婚禮上招刹,老公的妹妹穿的比我還像新娘。我一直安慰自己窝趣,他們只是感情好疯暑,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著哑舒,像睡著了一般妇拯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上洗鸵,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天越锈,我揣著相機(jī)與錄音,去河邊找鬼膘滨。 笑死甘凭,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的火邓。 我是一名探鬼主播对蒲,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贡翘!你這毒婦竟也來了蹈矮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤鸣驱,失蹤者是張志新(化名)和其女友劉穎泛鸟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踊东,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡北滥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了闸翅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片再芋。...
    茶點(diǎn)故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖坚冀,靈堂內(nèi)的尸體忽然破棺而出济赎,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布司训,位于F島的核電站构捡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏壳猜。R本人自食惡果不足惜勾徽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望统扳。 院中可真熱鬧喘帚,春花似錦、人聲如沸咒钟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盯腌。三九已至,卻和暖如春陨瘩,著一層夾襖步出監(jiān)牢的瞬間腕够,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工舌劳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帚湘,地道東北人。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓甚淡,卻偏偏與公主長得像大诸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贯卦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內(nèi)容