介紹
Realm 是一個 MVCC (多版本并發(fā)控制)數(shù)據(jù)庫歌豺,由Y Combinator公司在2014年7月發(fā)布一款支持運行在手機印叁、平板和可穿戴設(shè)備上的嵌入式數(shù)據(jù)庫,目標是取代SQLite呆贿。
Realm 本質(zhì)上是一個嵌入式數(shù)據(jù)庫酿箭,他并不是基于SQLite所構(gòu)建的。它擁有自己的數(shù)據(jù)庫存儲引擎垃你,可以高效且快速地完成數(shù)據(jù)庫的構(gòu)建操作椅文。和SQLite不同,它允許你在持久層直接和數(shù)據(jù)對象工作惜颇。在它之上是一個函數(shù)式風(fēng)格的查詢api皆刺,眾多的努力讓它比傳統(tǒng)的SQLite 操作更快 。
詳細介紹(如果進不去官还,看這個也行)
優(yōu)勢
如果在在使用它時候芹橡,連它的優(yōu)勢在哪都不知道的話就有點說不過去了。
-
易用
Ream 不是在SQLite基礎(chǔ)上的ORM望伦,它有自己的數(shù)據(jù)查詢引擎林说。并且十分容易使用煎殷。 -
快速
由于它是完全重新開始開發(fā)的數(shù)據(jù)庫實現(xiàn),所以它比任何的ORM速度都快很多腿箩,甚至比SLite速度都要快豪直。 -
跨平臺
Realm 支持 iOS & OS X (Objective?C & Swift) & Android。我們可以在這些平臺上共享Realm數(shù)據(jù)庫文件珠移,并且上層邏輯可以不用任何改動的情況下實現(xiàn)移植弓乙。 -
高級
Ream支持加密,格式化查詢钧惧,易于移植暇韧,支持JSON,流式api浓瞪,數(shù)據(jù)變更通知等高級特性 -
可視化
Realm 還提供了一個輕量級的數(shù)據(jù)庫查看工具懈玻,在Mac Appstore 可以下載“Realm Browser”這個工具,開發(fā)者可以查看數(shù)據(jù)庫當中的內(nèi)容乾颁,執(zhí)行簡單的插入和刪除數(shù)據(jù)的操作涂乌。(windows上還不清楚)
條件
- 目前不支持
Android
以外的Java
- Android Studio >= 1.5.1
- 較新的Android SDK版本
- JDK version >=7.
- 支持API 9(Android 2.3)以及之后的版本
使用
不介紹了,看代碼了英岭。
-
加入依賴
在project
的build
中加入依賴
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:2.2.1"
}
}
在
module
中加入
apply plugin: 'realm-android'
Realm從v1.0.0后湾盒,不支持Ecilpse,我們推薦使用Android Studio
創(chuàng)建model
創(chuàng)建一個User
類诅妹,需要繼承RealmObject
罚勾。支持public, protected和 private的類以及方法
public class User 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
來聲明 Realm 數(shù)據(jù)模型之外,還可以通過實現(xiàn) RealmModel
接口并添加 @RealmClass
修飾符來聲明吭狡。
@RealmClass
public class User implements RealmModel {
...
}
- 支持的屬性
boolean
,byte
,short
,int
,long
,float
,double
,String
,Date
和荧库,byte[]
,RealmObject
,RealmList<? extends RealmObject>
還支持Boolean
,Byte
,Short
,Integer
,Long
,Float
和Double
Tip:整數(shù)類型short
、int
和long
都被映射到 Realm 內(nèi)的相同類型(實際上為 long ) -
@PrimaryKey
——表示該字段是主鍵
使用過數(shù)據(jù)庫的同學(xué)應(yīng)該看出來了赵刑,PrimaryKey
就是主鍵分衫。使用@PrimaryKey
來標注,字段類型必須是字符串(String
)或整數(shù)(byte
般此,short
蚪战,int
或long
)以及它們的包裝類型(Byte
,Short
,Integer
, 或Long
)。不可以存在多個主鍵铐懊,使用字符串字段作為主鍵意味著字段被索引(注釋@PrimaryKey
隱式地設(shè)置注釋@Index
)邀桑。
@PrimaryKey
private String id;
-
@Required
——表示該字段非空
在某些情況下,有一些屬性是不能為null
的科乎。使用@Required
可用于用于強行要求其屬性不能為空壁畸,只能用于Boolean
,Byte
,Short
,Integer
,Long
,Float
,Double
,String
,byte[]
和Date
。在其它類型屬性上使用@Required
修飾會導(dǎo)致編譯失敗。
Tip:基本數(shù)據(jù)類型不需要使用注解@Required
捏萍,因為他們本身就不可為空太抓。
@Required
private String name;
-
@Ignore
——表示忽略該字段
被添加@Ignore
標簽后,存儲數(shù)據(jù)時會忽略該字段令杈。
@Ignore
private String name;
-
@Index
——添加搜索索引
為字段添加搜索索引走敌,這樣會使得插入的速度變慢,數(shù)據(jù)量也變得更大逗噩。不過在查詢速度將變得更快掉丽,建議只在優(yōu)化讀取性能的特定情況時添加索引。支持索引:String
异雁,byte
捶障,short
,int
纲刀,long
残邀,boolean
和Date
字段。
> **注意**:如果你創(chuàng)建Model并運行過柑蛇,然后修改了Model。那么就需要升級數(shù)據(jù)庫驱闷,否則會拋異常耻台。升級方式后面會提到
### **初始化**
使用默認配置
```java
Realm.init(this);
Realm mRealm = Realm.getDefaultInstance();
這時候會創(chuàng)建一個叫做 default.realm
的Realm文件,一般來說空另,這個文件位于/data/data/包名/files/盆耽。通過realm.getPath()
來獲得該Realm的絕對路徑。
注意:模擬器上運行時扼菠,
Realm.getDefaultInstance()
拋出異常摄杂,真機上沒問題(不止何故)
當然,我們還可以使用RealmConfiguration
來配置Realm
RealmConfiguration config = new RealmConfiguration.Builder()
.name("myrealm.realm") //文件名
.schemaVersion(0) //版本號
.build();
Realm realm = Realm.getInstance(config);
創(chuàng)建非持久化的Realm循榆,也就是保持在內(nèi)存中析恢,應(yīng)用關(guān)閉后就清除了。
RealmConfiguration myConfig = new RealmConfiguration.Builder(context)
.name("myrealm.realm")//保存在內(nèi)存中
.inMemory() .build();
RealmConfiguration
支持的方法:
-
Builder.name
: 指定數(shù)據(jù)庫的名稱秧饮。如不指定默認名為default映挂。 -
Builder.schemaVersion
: 指定數(shù)據(jù)庫的版本號。 -
Builder.encryptionKey
: 指定數(shù)據(jù)庫的密鑰盗尸。 -
Builder.migration
: 指定遷移操作的遷移類柑船。 -
Builder.deleteRealmIfMigrationNeeded
: 聲明版本沖突時自動刪除原數(shù)據(jù)庫。 -
Builder.inMemory
: 聲明數(shù)據(jù)庫只在內(nèi)存中持久化泼各。 -
build
: 完成配置構(gòu)建鞍时。
關(guān)閉Realm
記得使用完后,在onDestroy
中關(guān)閉Realm
@Override
protected void onDestroy() {
super.onDestroy();
// Close the Realm instance.
realm.close();
}
增
寫入操作需要在事務(wù)中進行,可以使用executeTransaction
方法來開啟事務(wù)逆巍。
- 使用
executeTransaction
方法插入數(shù)據(jù)
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User user = realm.createObject(User.class);
user.setName("Gavin");
user.setAge(23);
}
});
在execute
方法中執(zhí)行插入操作
注意:如果在UI線程中插入過多的數(shù)據(jù)及塘,可能會導(dǎo)致主線程擁塞。
- 使用
copyToRealmOrUpdate
或copyToRealm
方法插入數(shù)據(jù)
當Model中存在主鍵的時候蒸苇,推薦使用copyToRealmOrUpdate
方法插入數(shù)據(jù)磷蛹。如果對象存在,就更新該對象溪烤;反之味咳,它會創(chuàng)建一個新的對象。若該Model沒有主鍵檬嘀,使用copyToRealm
方法槽驶,否則將拋出異常。
final User user = new User();
user.setName("Jack");
user.setId("2");
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(user);
}
});
- 如果你用的是這樣的
modle
public class User2 extends RealmObject {
public String name;
public int age;
}
就這樣寫
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User2 user = realm.createObject(User2.class);
user.name = "Micheal";
user.age = 30;
}
});
- 如果User還有其他屬性是鸳兽,比如養(yǎng)了只
Dog
:
public class Dog extends RealmObject {
private String name;
private int age;
//getters and setters
}
對應(yīng)的User屬性中加入Dog
類
public class User extends RealmObject {
private String name;
private int age;
private Dog dog;
//getters and setters
}
如果你養(yǎng)了不止一只掂铐,你養(yǎng)了二哈、阿拉撕家...那你就要用到RealmList
了揍异。在User
中加入該屬性
private RealmList<Dog> dogs;
插入數(shù)據(jù)
@Override
public void execute(Realm realm) {
User user = realm.createObject(User.class);
user.setName("Gain");
user.setAge(23);
Dog dog1 = realm.createObject(Dog.class);
dog1.setAge(1);
dog1.setName("二哈");
user.getDogs().add(dog1);
Dog dog2 = realm.createObject(Dog.class);
dog2.setAge(2);
dog2.setName("阿拉撕家");
user.getDogs().add(dog2);
}
});
- 上面都是用可
executeTransaction
方法插入數(shù)據(jù)全陨,還有另一種方法可以用于插入數(shù)據(jù)——beginTransaction
和commitTransaction
mRealm.beginTransaction();//開啟事務(wù)
User user = mRealm.createObject(User.class);
user.setName("Gavin");
user.setId("3");
mRealm.commitTransaction();//提交事務(wù)
在插入前,先調(diào)用beginTransaction()
衷掷,完成后調(diào)用commitTransaction()
即可辱姨。
注意:在UI和后臺線程同時開啟創(chuàng)建write的事務(wù),可能會導(dǎo)致ANR錯誤戚嗅。為了避免該問題雨涛,可以使用
executeTransactionAsync
來實現(xiàn)。
- 使用
executeTransactionAsync
該方法會開啟一個子線程來執(zhí)行事務(wù)懦胞,并且在執(zhí)行完成后進行結(jié)果通知替久。
RealmAsyncTask transaction = mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User user = realm.createObject(User.class);
user.setName("Eric");
user.setId("4");
}
});
還可以加入監(jiān)聽
RealmAsyncTask transaction = mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User user = realm.createObject(User.class);
user.setName("Eric");
user.setId("4");
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
//成功回調(diào)
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
//失敗回調(diào)
}
});
注意:如果當Acitivity
或Fragment
被銷毀時,在OnSuccess
或OnError
中執(zhí)行UI操作躏尉,將導(dǎo)致程序奔潰 蚯根。用RealmAsyncTask .cancel();
可以取消事務(wù)
在onStop
中調(diào)用,避免crash
public void onStop () {
if (transaction != null && !transaction.isCancelled()) {
transaction.cancel();
}
}
- JSON
Realm還是個很nice的功能就是將Json字符串轉(zhuǎn)化為對象胀糜,厲害了我的Realm
(直接借用官方的例子)
// 一個city model
public class City extends RealmObject {
private String city;
private int id;
// getters and setters left out ...
}
// 使用Json字符串插入數(shù)據(jù)
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.createObjectFromJson(City.class, "{ city: \"Copenhagen\", id: 1 }");
}
});
// 使用InputStream插入數(shù)據(jù)
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
try {
InputStream is = new FileInputStream(new File("path_to_file"));
realm.createAllFromJson(City.class, is);
} catch (IOException e) {
throw new RuntimeException();
}
}
});
Realm 解析 JSON 時遵循如下規(guī)則:
- 使用包含空值(null)的 JSON 創(chuàng)建對象:
- 對于非必須(可為空值的屬性)稼锅,設(shè)置其值為 null;
- 對于必須(不可為空值的屬性)僚纷,拋出異常矩距;
- 使用包含空值(null)的 JSON 更新對象:
- 對于非必須(可為空值的屬性),設(shè)置其值為 null怖竭;
- 對于必須(不可為空值的屬性)锥债,拋出異常;
- 使用不包含對應(yīng)屬性的 JSON: * 該屬性保持不變
查
查找操作就比插入方便多了,并不需在事務(wù)中操作哮肚,直接查詢即可登夫。
-
findAll
——查詢
例:查詢所有的User
RealmResults<User> userList = mRealm.where(User.class).findAll();
這里使用RealmResults
來接受查詢到的結(jié)果,突然出現(xiàn)的RealmResults
可能會讓人懵逼允趟∧詹撸看看他的源碼,發(fā)現(xiàn)RealmResults
繼承了AbstractList
潮剪,而AbstractList
又實現(xiàn)了List
接口涣楷。好吧,原來實現(xiàn)了我們熟悉的List
接口抗碰。
public final class RealmResults<E extends RealmModel> extends AbstractList<E>
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
注意:
RealmResults
雖然實現(xiàn)了List
接口狮斗,不過有很多方法是不能用的。比如add
弧蝇、addAll
碳褒、remove
、clear
等看疗,調(diào)用后會直接拋異常沙峻。不過也不用當心誤用這些方法,因為它們都被標記為@Deprecated
了两芳。
-
findAllAsync
——異步查詢
當數(shù)據(jù)量較大摔寨,可能會引起ANR的時候,就可以使用findAllAsync
RealmResults<User> userList = mRealm.where(User.class)
.equalTo("name", "Gavin")
.findAllAsync();
值得注意的是盗扇,這里并不會馬上查到數(shù)據(jù),是有一定延時的沉填。也就是說疗隶,你馬上使用userList
的時候,里面是沒有數(shù)據(jù)的翼闹“弑牵可以注冊RealmChangeListener
監(jiān)聽器,或者使用isLoaded()
方法猎荠,判斷是否查詢完成
if (result.isLoaded()) {
// 完成查詢
}
-
findFirst
——查詢第一條數(shù)據(jù)
例:查詢User
表中的第一條數(shù)據(jù)
User user2 = mRealm.where(User.class).findFirst();
-
equalTo
——根據(jù)條件查詢
例:得到name
為Gavin
的用戶列表坚弱。
RealmResults<User> userList = mRealm.where(User.class)
.equalTo("name", "Gavin").findAll();
如果User
中還有Dog
屬性,希望根據(jù)Dog
的條件來獲取用戶:
例:查詢dogs.name
為二哈的User
RealmResults<User> userList = mRealm.where(User.class)
.equalTo("dogs.name", "二哈").findAll();
得到有養(yǎng)有dogs.name
為"二哈"的用戶列表(這里的dogs
是User
表中的屬性名)
-
equalTo
——多條件查詢
當然关摇,我們還經(jīng)常要用到多條件的查詢的功能荒叶。
例:找到用戶名為“Gavin”,且dogs.name
為“二哈”的User
RealmResults<User> userList = mRealm.where(User.class)
.equalTo("name", "Gavin").findAll();
RealmResults<User> userList = user5.where()
.equalTo("dogs.name", "二哈").findAll();
上面先找到name
為“Gavin”的User
列表输虱,然后再得到的結(jié)果中查詢dogs.name
為“二哈”
覺得這樣寫太麻煩些楣?我也是這樣想的,所以還可以這樣寫
RealmResults<User> userList = mRealm.where(User.class)
.equalTo("name", "Gavin")
.equalTo("dogs.name", "二哈")
.findAll();
是不是很清爽~~~
更多查詢條件
上面就展示了equalTo
的用法。當然愁茁,查詢還有更多的用法蚕钦,我就不一一示例了。已知的方法如下:
sum()
:對指定字段求和鹅很。
average()
:對指定字段求平均值嘶居。
min()
: 對指定字段求最小值。
max()
: 對指定字段求最大值促煮。count : 求結(jié)果集的記錄數(shù)量邮屁。
findAll()
: 返回結(jié)果集所有字段,返回值為RealmResults隊列
findAllSorted()
: 排序返回結(jié)果集所有字段污茵,返回值為RealmResults隊列
between()
,greaterThan()
,lessThan()
,greaterThanOrEqualTo()
&lessThanOrEqualTo()
equalTo()
¬EqualTo()
contains()
,beginsWith()
&endsWith()
isNull()
&isNotNull()
isEmpty()
&isNotEmpty()
RealmQuery
以及or
的使用
在使用where()
方法時樱报,能得到一個RealmQuery
對象,使用方法如下:
例:查詢name
為“Gavin”和“Eric”的用戶
RealmQuery<User> query = mRealm.where(User.class);
query.equalTo("name", "Gavin");
query.or().equalTo("name", "Eric");
RealmResults<User> userList = query.findAll();
這種情況下就要用到or()方法
這么一大串泞当,你又覺得麻煩了迹蛤?沒事,繼續(xù)簡化襟士。
RealmResults<User> userList = mRealm.where(User.class)
.equalTo("name", "Gavin")
.or().equalTo("name", "Eric")
.findAll();
Tip:查詢的時候你不用當心得到的RealmResults
為null
盗飒。如果查詢的結(jié)果為空,那么RealmResults
的size
為0
- 排序
查詢結(jié)束后陋桂,還可以進行排序逆趣,就像這樣:
RealmResults<User> userList = mRealm.where(User.class) .findAll();
userList = result.sort("age"); //根據(jù)age,正序排列
userList = result.sort("age", Sort.DESCENDING);//逆序排列
- 聚合
RealmResult
自帶一些聚合方法:
RealmResults<User> results = realm.where(User.class).findAll();
long sum = results.sum("age").longValue();
long min = results.min("age").longValue();
long max = results.max("age").longValue();
double average = results.average("age");
long matches = results.size();
改
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
//先查找后得到User對象
User user = mRealm.where(User.class).findFirst();
user.setAge(26);
}
});
修改也是需要在事務(wù)中操作嗜历。
使用查詢語句得到數(shù)據(jù)宣渗,然后將內(nèi)容改了即可。
刪
- 使用
deleteFromRealm()
//先查找到數(shù)據(jù)
final RealmResults<User> userList = mRealm.where(User.class).findAll();
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
userList.get(0).deleteFromRealm();
}
});
- 使用
deleteFromRealm(int index)
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
userList.deleteFromRealm(0);
}
});
- 更多方法:
userList.deleteFirstFromRealm(); //刪除user表的第一條數(shù)據(jù)
userList.deleteLastFromRealm();//刪除user表的最后一條數(shù)據(jù)
results.deleteAllFromRealm();//刪除user表的全部數(shù)據(jù)
版本升級
當數(shù)據(jù)結(jié)構(gòu)發(fā)生變化是梨州,需要升級數(shù)據(jù)庫痕囱。對于Realm來說,數(shù)據(jù)庫升級就是遷移操作暴匠,把原來的數(shù)據(jù)庫遷移到新結(jié)構(gòu)的數(shù)據(jù)庫鞍恢。(體驗:略麻煩)
- 例1:
User
類發(fā)生變化,移除age
每窖,新增個@Required
的id
字段帮掉。
User
版本:version 0
String name;
int age;
User
版本:version 1
@Required
String id;
String name;
創(chuàng)建遷移類CustomMigration
,需要實現(xiàn)RealmMigration
接口窒典。執(zhí)行版本升級時的處理:
/**
* 升級數(shù)據(jù)庫
*/
class CustomMigration implements RealmMigration {
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
RealmSchema schema = realm.getSchema();
if (oldVersion == 0 && newVersion == 1) {
RealmObjectSchema personSchema = schema.get("User");
//新增@Required的id
personSchema
.addField("id", String.class, FieldAttribute.REQUIRED)
.transform(new RealmObjectSchema.Function() {
@Override
public void apply(DynamicReal
mObject obj) {
obj.set("id", "1");//為id設(shè)置值
}
})
.removeField("age");//移除age屬性
oldVersion++;
}
}
}
使用Builder.migration
升級數(shù)據(jù)庫蟆炊,將版本號改為1(原版本號:0)。當Realm發(fā)現(xiàn)新舊版本號不一致時瀑志,會自動使用該遷移類完成遷移操作盅称。
RealmConfiguration config = new RealmConfiguration.Builder()
.name("myrealm.realm") //文件名
.schemaVersion(1)
.migration(new CustomMigration())//升級數(shù)據(jù)庫
.build();
- 例2:加入
Dog
類肩祥,User
中加入Dog
集合。
User
版本:version 1
@Required
String id;
String name;
User
版本:version 2
@Required
private String id;
private String name;
private RealmList<Dog> dogs;
Dog
類
public class Dog extends RealmObject {
private String name;
private int age;
}
在遷移類CustomMigration
中缩膝,繼續(xù)添加處理方法混狠。
if (oldVersion == 1 && newVersion == 2) {
//創(chuàng)建Dog表
RealmObjectSchema dogSchema = schema.create("Dog");
dogSchema.addField("name", String.class);
dogSchema.addField("age", int.class);
//User中添加dogs屬性
schema.get("User")
.addRealmListField("dogs", dogSchema)
.transform(new RealmObjectSchema.Function() {
@Override
public void apply(DynamicRealmObject obj) {
//為已存在的數(shù)據(jù)設(shè)置dogs數(shù)據(jù)
DynamicRealmObject dog = realm.createObject("Dog");
dog.set("name", "二哈");
dog.set("age", 2);
obj.getList("dogs").add(dog);
}
});
oldVersion++;
}
- 更多用法——
RealmObjectSchema
例:取消id必填:
personSchema.setNullable("id", true):
例:移除id字段
personSchema.removeField("id");
例:重命名
personSchema..renameField("id", "userId");
- 更多用法——
DynamicRealmObject
例:獲取id
String id = obj.getString("id");
例:為字段設(shè)置值
obj.setString("name", "Gavin");
obj.setInt("id", 1);
obj.setLong("id", 1);
疑問:我在debug時發(fā)現(xiàn)這樣的數(shù)據(jù),如圖:
什么疾层,dogs将饺、id、name的值怎么都是null痛黎?這~~
開始我還以為升級時數(shù)據(jù)丟失予弧,不過在圖中userList第0條數(shù)據(jù)的右邊看到了我的數(shù)據(jù),于是我展開了里面的內(nèi)容湖饱,如圖:
好吧掖蛤,他并不是我想象中的那種存法,我已經(jīng)不知道他內(nèi)部是怎么實現(xiàn)的了井厌。(還望大神賜教)
加密
(官方原文)
Realm 文件可以通過傳遞一個512位(64字節(jié))的密鑰參數(shù)給 Realm.getInstance().encryptionKey()
來加密存儲在磁盤上蚓庭。
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
RealmConfiguration config = new RealmConfiguration.Builder()
.encryptionKey(key)
.build();
Realm realm = Realm.getInstance(config);
保證了所有永久性存儲在磁盤上的數(shù)據(jù)都是通過標準 AES-256 加密的。每次創(chuàng)建新的 Realm 實例的時候仅仆,都需要提供相同的密鑰器赞。
參考 examples/encryptionExample。這個例子演示了如何通過 Android KeyStore 來安全地存儲密鑰墓拜。
適配器(Adapter)
(官方原文)
Realm提供了一些抽象的工具類來方便地將 OrderedRealmCollection
(RealmResults
和 RealmList
都實現(xiàn)了這個借口)展示到UI控件上港柜。
你需要在 app 的 build.gradle
中添加額外的依賴以使用這些適配器夏醉。
dependencies {
compile 'io.realm:android-adapters:1.4.0'
}
Intents
(官方原文)
你不可以直接通過 intent
傳遞 RealmObject
,建議你只傳遞RealmObject
的標識符涌韩。舉個常用例子畔柔,假如你的對象擁有一個主鍵,請通過intent
的 bundle
來傳遞這個主鍵的值贸辈。
// Assuming we had a person class with a @PrimaryKey on the 'id' field ...
Intent intent = new Intent(getActivity(), ReceivingService.class);
intent.putExtra("person_id", person.getId());
getActivity().startService(intent);
在接受方(Activity
释树、Service
肠槽、IntentService
擎淤、BroadcastReceiver
及其它)從 bundle
中解析出這個主鍵然后打開Realm
查詢得到這個 RealmObject
。
// in onCreate(), onHandleIntent(), etc.
String personId = intent.getStringExtra("person_id");
Realm realm = Realm.getDefaultInstance();
Person person = realm.where(Person.class).equalTo("id", personId).findFirst();// do something with the person ...
realm.close();
可以參考 threading example 中的 Object Passing部分秸仙。該示例展示了在安卓開發(fā)中常用的如何傳遞 id 并且得到對應(yīng)的 RealmObject
嘴拢。
RxJava
對于這么火的RxJava,Realm又怎么會放過他寂纪。
Realm 包含了對 RxJava 的原生支持席吴。如下類可以被暴露為一個 Observable:Realm, RealmResults, RealmObject, DynamicRealm 和 DynamicRealmObject赌结。
(直接用一個官方的例子)
Realm realm = Realm.getDefaultInstance();
GitHubService api = retrofit.create(GitHubService.class);
realm.where(Person.class).isNotNull("username").findAllAsync().asObservable()
.filter(persons.isLoaded)
.flatMap(persons -> Observable.from(persons))
.flatMap(person -> api.user(person.getGithubUserName())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(user -> showUser(user));
這里使用asObservable
輕松轉(zhuǎn)換成RxJava中的Observable
,使用.filter(persons.isLoaded)
來判斷是否已查詢完成孝冒。到這里柬姚,熟悉RxJava的同學(xué)應(yīng)該已經(jīng)看明白了~~∽校可能還有人會一臉懵逼量承,->
? 這是什么鬼?哈哈穴店,這叫Lambda撕捍,有時間可以去看看。
也許還有很多同學(xué)不了解RxJava泣洞,這里極力推薦給 Android 開發(fā)者的 RxJava 詳解忧风。
終于寫完了~~~說好易用的,沒想到內(nèi)容居然這么多球凰。
源碼地址
參考資料
官方文檔
GitHub
Realm for Android快速入門教程
Android開發(fā)筆記(八十五)手機數(shù)據(jù)庫Realm
在Android加入和使用Realm
Android 進階之第三方庫的介紹 Realm [一] 基礎(chǔ)用法
以上有錯誤之處狮腿,感謝指出