Realm數(shù)據(jù)庫(kù)(移動(dòng)設(shè)備數(shù)據(jù)庫(kù)解決方案)

Realm 是我見過的說明文檔寫得比較齊全的第三方數(shù)據(jù)庫(kù)框架种蝶,早期的版本中,還有對(duì)應(yīng)的中文版說明文檔,截止當(dāng)前,realm的java版本Latest版本為:1.2.0.
官網(wǎng)傳送門:https://realm.io

Getting Started

一、project level的build.gradle添加如下內(nèi)容

project-level-build-gradle.png
buildscript {
  repositories { jcenter()
  } 
  dependencies {
   classpath "io.realm:realm-gradle-plugin:1.2.0" 
  }
}
project-level-build-gradle.png

二、在application level#build.gradle中添加以下內(nèi)容

application-level-build-gradle.png
apply plugin: 'realm-android'
application-level-build-gradle.png

你可以在以下地方看到這兩個(gè)例子
Project level build.gradle
Application level build.gradle

以上呜袁,刷新你的gradle依賴,realm就簡(jiǎn)單的被集成成功了.

Models的創(chuàng)建

要自定義創(chuàng)建Models,必須繼承RealmObject類

public class User extends RealmObject {
  /**public或protected 也可以*/
  private String name; 
  private int age;
// Standard getters & setters generated by your IDE… 
}

屬性支持

Realm 支持以下屬性類型

  • boolean
  • byte
  • short
  • int
  • long
  • float
  • double
  • String
  • Date
  • byte[]
    ------------------------其中---------------------------
    byte/short/int/long在Realm中是以long的形式保存的蛉迹,而包裝類型
  • Boolean
  • Byte
  • Short
  • Integer
  • Long
  • Float
  • Double
    亦可在Realm中使用傅寡,只不過使用封裝類型,屬性值可能被設(shè)置成空.

@Required注解

在某些應(yīng)用場(chǎng)合,空值時(shí)不被允許的北救,這時(shí)候可以使用@Required注解告訴Realm去檢查荐操,禁止空值的出現(xiàn),當(dāng)然主鍵以及RealmList默認(rèn)自帶@Required注解(隱必需)

@Ignore注解

@Ignore可以告訴Realm 對(duì)特定的參數(shù)取消系列化珍策,持有該注解的參數(shù)不會(huì)被持久化到數(shù)據(jù)庫(kù)中.

自動(dòng)更新持久化對(duì)象

RealmObject對(duì)象數(shù)據(jù)發(fā)生改變時(shí)無需用戶去刷新,Realm會(huì)自動(dòng)更新對(duì)象的值

realm.executeTransaction(new Realm.Transaction() { 
  @Override public void execute(Realm realm) {
   Dog myDog = realm.createObject(Dog.class);
   myDog.setName("Fido"); myDog.setAge(1);
  }
});
Dog myDog = realm.where(Dog.class).equalTo("age",1).findFirst();
realm.executeTransaction(new Realm.Transaction() { 
  @Override public void execute(Realm realm) { 
  Dog myPuppy=realm.where(Dog.class).equalTo("age",1).findFirst();
  myPuppy.setAge(2); 
  }
});
myDog.getAge(); // => 2

@Index注解 為表添加索引

使用@Index可以為表中的屬性添加索引托启,使用@Index注解的后果是:

  • 它會(huì)使Insert操作更耗時(shí),并且數(shù)據(jù)文件更大
  • 查詢更快
    所以在適當(dāng)?shù)那闆r下攘宙,為了優(yōu)化讀取性能屯耸,建議使用@Index索引,當(dāng)然使用索引的屬性類型最好是String/byte/short/int/long/boolean/Date中的一種蹭劈。

數(shù)據(jù)庫(kù)升級(jí)(數(shù)據(jù)庫(kù)遷移)

當(dāng)我們使用數(shù)據(jù)庫(kù)時(shí)疗绣,無時(shí)不刻要應(yīng)對(duì)數(shù)據(jù)庫(kù)模型的變化,Realm的數(shù)據(jù)庫(kù)模型用標(biāo)準(zhǔn)的java對(duì)象來定義铺韧,改變數(shù)據(jù)模型只需要改變JAVA數(shù)據(jù)對(duì)象定義多矮。
如果不存在舊的數(shù)據(jù)庫(kù),那么代碼的改變會(huì)立即反應(yīng)到數(shù)據(jù)庫(kù)上哈打,但是如果已經(jīng)有舊版本數(shù)據(jù)庫(kù)文件存在塔逃,Realm會(huì)拋出異常提示數(shù)據(jù)庫(kù)需要升級(jí),此時(shí)請(qǐng)?jiān)?RealmConfiguration 設(shè)置 schema 版本和 migration 代碼來正確處理并避免該異常拋出料仗。

RealmConfiguration config = newRealmConfiguration.Builder(context) 
.schemaVersion(2) // 當(dāng)數(shù)據(jù)庫(kù)發(fā)生改變時(shí)湾盗,Version必須增加 
.migration(new MyMigration()) // 執(zhí)行數(shù)據(jù)庫(kù)升級(jí)、而不是拋異常
.build()

MyMigration 數(shù)據(jù)庫(kù)升級(jí)操作 例子

RealmMigration migration = new RealmMigration() { 
@Override 
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) { 
  // DynamicRealm exposes an editable schema 
  RealmSchema schema = realm.getSchema(); 
  // Migrate to version 1: Add a new class 
  // Example: 
  // public Person extends RealmObject { 
  // private String name; 
  // private int age; 
  // // getters and setters left out for brevity 
  // } 
  if (oldVersion == 0) { 
  schema.create("Person")
   .addField("name", String.class)
   .addField("age", int.class); 
    oldVersion++; 
  }
  // Migrate to version 2: Add a primary key + object references 
  // Example: 
  // public Person extends RealmObject { 
  // private String name; 
  // @PrimaryKey 
  // private int age; 
  // private Dog favoriteDog; 
  // private RealmList<Dog> dogs; 
  // // getters and setters left out for brevity 
  // }
  if (oldVersion == 1) {
  schema.get("Person") .addField("id",
  long.class,FieldAttribute.PRIMARY_KEY) 
  .addRealmObjectField("favoriteDog", schema.get("Dog")) 
  .addRealmListField("dogs", schema.get("Dog")); 
  oldVersion++;
   } 
  }
}

如果以上的例子看得不過癮立轧,你也可以直接參考官方提供的
數(shù)據(jù)遷移例子
當(dāng)然格粪,如果舊數(shù)據(jù)庫(kù)不存在的情況下,數(shù)據(jù)庫(kù)遷移(我更喜歡叫它數(shù)據(jù)庫(kù)更新)就沒必要了氛改,而數(shù)據(jù)庫(kù)存在的情況下匀借,如果你不關(guān)心舊數(shù)據(jù)庫(kù)的數(shù)據(jù)丟失,那么也可以這樣做

RealmConfiguration config = new RealmConfiguration.Builder(context) 
.deleteRealmIfMigrationNeeded() .build()

以上的配置平窘,當(dāng)發(fā)現(xiàn)數(shù)據(jù)庫(kù)需要更新的時(shí)候,Realm會(huì)自動(dòng)把原來的數(shù)據(jù)庫(kù)(.realm文件)刪除并重新創(chuàng)建,不過這種方式比較適合開發(fā)初期.

數(shù)據(jù)寫入

數(shù)據(jù)庫(kù)的訪問及查詢可以在任何時(shí)間進(jìn)行操作(讀取事務(wù)是隱式的凳怨,無需用戶進(jìn)行聲明)瑰艘,但是數(shù)據(jù)庫(kù)的寫入(比如增刪改)則需要用戶聲明一個(gè)Write事務(wù)是鬼,并將所有操作包含在Write事務(wù)中,事務(wù)可以被提交也可以被取消紫新,當(dāng)事務(wù)提交時(shí)均蜜,只有所有的更改都成功持久化后,事務(wù)提交才會(huì)成功芒率,當(dāng)事務(wù)被取消時(shí)囤耳,所有的更改將被丟棄.使用寫入事務(wù),可以保證數(shù)據(jù)的一致性.
事務(wù)是線程安全的.

// Obtain a Realm instance
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
//... add or update objects here ...
realm.commitTransaction();

當(dāng)在你的業(yè)務(wù)邏輯過程中偶芍,需要取消更改充择,你可以使用:

realm.beginTransaction();
User user = realm.createObject(User.class);
// ...
realm.cancelTransaction();

需要說明的是,寫入事務(wù)之間會(huì)相互阻塞匪蟀,如果一個(gè)寫入事務(wù)正在執(zhí)行椎麦,那么其他線程的寫入事務(wù)就會(huì)阻塞它所在的線程,(同時(shí)在UI線程及后臺(tái)線程開啟事務(wù)有可能導(dǎo)致ANR的問題產(chǎn)生)【TODO 寫入事務(wù)是否最好都移動(dòng)到后臺(tái)線程上去執(zhí)行?】官方提供建議使用 異步事務(wù)(async transactions)方法以避免阻塞 UI 線程.

創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象的方法

一、通過Realm實(shí)例化對(duì)象

realm.beginTransaction();
User user = realm.createObject(User.class); // Create a new object
user.setName("John");
user.setEmail("john@corporation.com");
realm.commitTransaction();

二材彪、 realm.copyToRealm() 添加

User user = new User("John");
user.setEmail("john@corporation.com");
// Copy the object to Realm. Any further changes must happen on realmUser
realm.beginTransaction();
User realmUser = realm.copyToRealm(user);
realm.commitTransaction();

事務(wù)執(zhí)行

除了手動(dòng)調(diào)用realm.beginTransaction()观挎、realm.commitTransaction()和
realm.cancelTransaction()方法之外,只用 [realm.executeTransaction()](https://realm.io/cn/docs/java/latest/api/io/realm/Realm.html#executeTransaction(io.realm.Realm Transaction)) 會(huì)自動(dòng)處理事務(wù)的開始于提交段化,并在錯(cuò)誤的時(shí)候嘁捷,取消事務(wù).

realm.executeTransaction(new Realm.Transaction() {
  @Override 
  public void execute(Realm realm) {
    User user = realm.createObject(User.class); 
    user.setName("John"); 
    user.setEmail("john@corporation.com");
 }
});

異步事務(wù)(Asynchronous Transactions)

使用事務(wù)的時(shí)候,因?yàn)槭聞?wù)的處理是不定時(shí)的显熏,在UI線程上雄嚣,很容易造成應(yīng)用ANR,在此官方文檔建議我們使用異步事務(wù)佃延,耗時(shí)的操作放到后臺(tái)線程去處理现诀,處理結(jié)果通過回調(diào)返回給UI線程

realm.executeTransactionAsync(new Realm.Transaction() { 
  @Override 
  public void execute(Realm bgRealm) { 
    User user = bgRealm.createObject(User.class);
    user.setName("John"); 
    user.setEmail("john@corporation.com");
 }}, new Realm.Transaction.OnSuccess() {
   @Override 
   public void onSuccess() { 
      // Transaction was a success. 
 }}, new Realm.Transaction.OnError() {
     @Override
     public void onError(Throwable error) {
       // Transaction failed and was automatically canceled. 
  }
});

更新字符串及byte數(shù)組

Realm的寫操作針對(duì)是的整個(gè)屬性,而非屬性中的某一個(gè)字符履肃,如果你有這樣的需求仔沿,請(qǐng)操作一下的例子:

realm.executeTransaction(new Realm.Transaction() { 
  @Override 
  public void execute(Realm realm) {
     bytes[] bytes = realmObject.binary; bytes[4] = 'a'; realm.binary =bytes; 
  }
});

查詢

查詢條件
Realm 支持以下查詢條件:
between()、greaterThan()尺棋、lessThan()封锉、greaterThanOrEqualTo()
和 lessThanOrEqualTo()

equalTo()和 notEqualTo()

contains()、beginsWith()和 endsWith()

isNull() 和 isNotNull()

isEmpty()和 isNotEmpty()

并非所有條件都適用于所有數(shù)據(jù)類型膘螟,具體請(qǐng)參考 RealmQuery
API
成福。

Notifications

Listener只工作于 Looper 線程。對(duì)于非 Looper 線程請(qǐng)使用
Realm.watitForChange().

當(dāng)后臺(tái)線程向 Realm 添加數(shù)據(jù)荆残,你的 UI 線程或者其它線程可以添加一個(gè)監(jiān)聽器來獲取數(shù)據(jù)改變的通知奴艾。監(jiān)聽器在 Realm 數(shù)據(jù)改變的時(shí)候會(huì)被觸發(fā)。

public class MyActivity extends Activity {
   private Realm realm; private RealmChangeListener realmListener;   
   @Override 
   protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState);
      realm = Realm.getDefaultInstance(); 
      reamlListener = new RealmChangeListener<Realm>() {
      @Override 
      public void onChange(Realm realm) {
        // ... do something with the updates (UI, etc.) ... 
      }}; 
   realm.addChangeListener(realmListener);
 } 
@Override 
protected void onDestroy() {
   super.onDestroy(); 
   // Remove the listener. 
   realm.removeChangeListener(realmListener);
   // Close the Realm instance.
   realm.close(); 
}}

除了在 Realm實(shí)例上添加監(jiān)聽器以外内斯,你還可以在 RealmObject和 RealmResults實(shí)例上添加監(jiān)聽器蕴潦。你可以通過這樣的方式來監(jiān)視對(duì)象和查詢結(jié)果的改變像啼。另外,當(dāng)監(jiān)聽回調(diào)函數(shù)被調(diào)用時(shí)潭苞,相應(yīng)的數(shù)據(jù)已經(jīng)被更新忽冻,你不需要去做刷新操作。

public class MyActivity extends Activity { 
  private Realm realm; 
  private RealmChangeListener puppiesListener;
  private RealmChangeListener dogListener; 
  private RealmResults<Dog> puppies;
  private Dog dog;
 @Override
 protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    realm = Realm.getDefaultInstance();
    puppiesListener = new   
    RealmChangeListener<RealmResults<Dog>>() {
     @Override
     public void onChange(RealmResults<Dog> puppies) { 
    // ... do something with the updated puppies instance
   }}; 
  // Find all the puppies 
  puppies = realm.where(Dog.class).lessThanOrEqualTo("age", 2).findAll();
  puppies.addChangeListener(puppiesListener);
  dogListener = new RealmChangeListener<Dog>() { 
   @Override
  public void onChange(Dog dog) { 
      // ... do something with the updated Dog instance
 }};
 dog = realm.where(Dog.class).equals("name", "Fido").findFirst(); 
 dog.addChangeListener(dogListener); 
} 
 @Override
 protected void onDestroy() { 
  super.onDestroy(); 
  // Remove the listeners    
  puppies.removeChangeListener(puppiesListener);   
  dog.removeChangeListener(dogListener); 
  // Close the Realm instance. 
  realm.close(); 
}}

最后此疹,這些監(jiān)聽器同樣會(huì)在監(jiān)聽對(duì)象的引用對(duì)象改變時(shí)被觸發(fā)僧诚,請(qǐng)見示例:

Person person = realm.where(Person.class).findFirst();person.getDogs(); 
// => 2 - Assume there are 2 dogs in the list
person.addChangeListener(new RealmChangeListener<Person>() { 
@Override
 public void onChange(Person person) { 
// React to the change in the Person instance. 
// This will also get called when any referenced dogs are updated. 
} });
Dog dog = person.getDogs().get(0);
realm.beginTransaction();
dog.setAge(5);realm.commitTransaction();
// Person change listener is called on the next iteration of the run loop because
// a referenced dog object changed.

NEXT 等待補(bǔ)充中....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蝗碎,隨后出現(xiàn)的幾起案子湖笨,更是在濱河造成了極大的恐慌,老刑警劉巖衍菱,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赶么,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡脊串,警方通過查閱死者的電腦和手機(jī)辫呻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琼锋,“玉大人放闺,你說我怎么就攤上這事÷瓶玻” “怎么了怖侦?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)谜叹。 經(jīng)常有香客問我匾寝,道長(zhǎng),這世上最難降的妖魔是什么荷腊? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任艳悔,我火速辦了婚禮,結(jié)果婚禮上女仰,老公的妹妹穿的比我還像新娘猜年。我一直安慰自己,他們只是感情好疾忍,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布乔外。 她就那樣靜靜地躺著,像睡著了一般一罩。 火紅的嫁衣襯著肌膚如雪杨幼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音差购,去河邊找鬼补疑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛歹撒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诊胞,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼暖夭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了撵孤?” 一聲冷哼從身側(cè)響起迈着,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邪码,沒想到半個(gè)月后裕菠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闭专,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年奴潘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片影钉。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡画髓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出平委,到底是詐尸還是另有隱情奈虾,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布廉赔,位于F島的核電站肉微,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜡塌。R本人自食惡果不足惜碉纳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岗照。 院中可真熱鬧村象,春花似錦、人聲如沸攒至。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)迫吐。三九已至库菲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間志膀,已是汗流浹背熙宇。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工鳖擒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烫止。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓蒋荚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親馆蠕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子期升,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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