Android realm 相關使用教程

一、Realm簡介

數據庫Realm,是用來替代sqlite的一種解決方案,它有一套自己的數據庫存儲引擎,比sqlite更輕量級,擁有更快的速度,并且具有很多現代數據庫的特性,比如支持JSON,流式api,數據變更通知,自動數據同步,簡單身份驗證,訪問控制,事件處理,最重要的是跨平臺,目前已有Java,Objective C,Swift,React-Native,Xamarin這五種實現。相關地址

Realm

二、環境配置
(1) 在項目的 build.gradle 文件中添加如下 class path 依賴。

項目的 build.gradle
buildscript { 
  repositories {
     jcenter() 
  } 
  dependencies { 
  classpath "io.realm:realm-gradle-plugin:2.0.2" 
  }
}

(2) 在app的build文件加上

app的build
apply plugin: 'realm-android'

三、初始化Realm
(1) 在Application的oncreate()方法中Realm.init()

public class MyApplication extends Application {
 @Override 
  public void onCreate() { 
    super.onCreate(); Realm.init(this); 
 }
}

(2)在Application的oncreate()方法中對Realm進行相關配置
①使用默認配置

public class MyApplication extends Application { 
  @Override 
  public void onCreate() { 
  super.onCreate();
   // The Realm file will be located in Context.getFilesDir() with name "default.realm"      
  Realm.init(this); 
  RealmConfiguration config = new RealmConfiguration.Builder().build();  
  Realm.setDefaultConfiguration(config); 
  }
}

②使用自定義配置

public class MyApplication extends Application { 
  @Override 
  public void onCreate() { 
  super.onCreate(); 
  Realm.init(this);
  RealmConfiguration config = new RealmConfiguration.Builder() .name("myRealm.realm") .deleteRealmIfMigrationNeeded() .build();
  Realm.setDefaultConfiguration(config); 
 }
}

(3)在AndroidManifest.xml配置自定義的Application

<application android:name=".MyApplication" .../>

四、創建實體
(1)新建一個類繼承RealmObject

public class Dog extends RealmObject {
   @PrimaryKey   // 必須要有一個主鍵
   private String id; 

   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; 
 } 
 public String getId() {
  return id; 
 } 
 public void setId(String id) { 
 this.id = id; 
 }
}

多對多的關系:

public class Contact extends RealmObject { 
  public String name; 
  public RealmList<Email> emails;

  public class Email extends RealmObject { 
  public String address;
  public boolean active;
  }
}

(2)其他相關說明

1、支持的數據類型:
boolean, byte, short, int, long, float, double, String, Date and byte[]
在Realm中byte, short, int, long最終都被映射成long類型
2、注解說明
@PrimaryKey
①字段必須是String、 integer、byte、short、 int、long 以及它們的封裝類Byte, Short, Integer, and Long
②使用了該注解之后可以使用copyToRealmOrUpdate()方法,通過主鍵查詢它的對象,如果查詢到了,則更新它,否則新建一個對象來代替。
③使用了該注解將默認設置(@index)注解
④使用了該注解之后,創建和更新數據將會慢一點,查詢數據會快一點。
@Required
數據不能為null
@Ignore
忽略,即該字段不被存儲到本地
@Index

為這個字段添加一個搜索引擎,這將使插入數據變慢、數據增大,但是查詢會變快。建議在需要優化讀取性能的情況下使用。

五、增
(1)實現方法一:事務操作
類型一 :新建一個對象,并進行存儲

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

類型二:復制一個對象到Realm數據庫

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

(2)實現方法二:使用事務塊

Realm mRealm=Realm.getDefaultInstance();
final User user = new User("John");
user.setEmail("john@corporation.com");
mRealm.executeTransaction(new Realm.Transaction() {
 @Override
  public void execute(Realm realm) { 
      realm.copyToRealm(user); 
} 
});

六、刪

Realm mRealm=Realm.getDefaultInstance(); 
final RealmResults<Dog> dogs= mRealm.where(Dog.class).findAll(); mRealm.executeTransaction(new Realm.Transaction() {
  @Override 
  public void execute(Realm realm) { 
  Dog dog=dogs.get(5); 
  dog.deleteFromRealm(); 
  //刪除第一個數據 
  dogs.deleteFirstFromRealm();
   //刪除最后一個數據 
  dogs.deleteLastFromRealm(); 
  //刪除位置為1的數據 
  dogs.deleteFromRealm(1); 
  //刪除所有數據 
  dogs.deleteAllFromRealm(); 
  } 
});

同樣也可以使用同上的beginTransaction和commitTransaction方法進行刪除
七、改

 Realm mRealm=Realm.getDefaultInstance();
 Dog dog = mRealm.where(Dog.class).equalTo("id", id).findFirst();
 mRealm.beginTransaction();
 dog.setName(newName);
 mRealm.commitTransaction();

同樣也可以用事物塊來更新數據
八、查
(1)查詢全部
查詢結果為RealmResults

public List<Dog> queryAllDog() { 
Realm mRealm=Realm.getDefaultInstance();
 RealmResults<Dog> dogs = mRealm.where(Dog.class).findAll();
 return mRealm.copyFromRealm(dogs); 
}

(2)條件查詢

public Dog queryDogById(String id) {
Realm mRealm=Realm.getDefaultInstance(); 
Dog dog = mRealm.where(Dog.class).equalTo("id", id).findFirst(); 
return dog; 
}

常見的條件如下(詳細資料請查官方文檔):
between(), greaterThan(), lessThan(), greaterThanOrEqualTo() & lessThanOrEqualTo()

equalTo() & notEqualTo()

contains(), beginsWith() & endsWith()

isNull() & isNotNull()

isEmpty() & isNotEmpty()

(3)對查詢結果進行排序

/** 
* query (查詢所有)
 */ 
public List<Dog> queryAllDog() { 
RealmResults<Dog> dogs = mRealm.where(Dog.class).findAll(); 
/** 
* 對查詢結果,按Id進行排序,只能對查詢結果進行排序 
*/
 //增序排列 
dogs=dogs.sort("id"); 
//降序排列 
dogs=dogs.sort("id", Sort.DESCENDING); 
return mRealm.copyFromRealm(dogs);
 }

(4)其他查詢
sum,min,max,average只支持整型數據字段

/** 
* 查詢平均年齡 
*/ 
private void getAverageAge() { 
double avgAge= mRealm.where(Dog.class).findAll().average("age"); 
}
 /** 
* 查詢總年齡 
*/ 
private void getSumAge() { 
 Number sum= mRealm.where(Dog.class).findAll().sum("age");
 int sumAge=sum.intValue(); 
} 
/** 
* 查詢最大年齡
 */ 
private void getMaxId(){ 
  Number max= mRealm.where(Dog.class).findAll().max("age");
 int maxAge=max.intValue();
 }

九、異步操作
大多數情況下,Realm的增刪改查操作足夠快,可以在UI線程中執行操作。但是如果遇到較復雜的增刪改查,或增刪改查操作的數據較多時,就可以子線程進行操作。
(1)異步增:

private void addCat(final Cat cat) { 
RealmAsyncTask addTask= mRealm.executeTransactionAsync(new Realm.Transaction() { 
@Override 
public void execute(Realm realm) { 
realm.copyToRealm(cat); 
} }, 
new Realm.Transaction.OnSuccess() { 
@Override 
public void onSuccess() { 
ToastUtil.showShortToast(mContext,"收藏成功"); } }, 
new Realm.Transaction.OnError() { 
@Override 
public void onError(Throwable error) { 
ToastUtil.showShortToast(mContext,"收藏失敗"); 
} 
});
 }

最后在銷毀Activity或Fragment時,要取消掉異步任務

@Override 
protected void onDestroy() { 
  super.onDestroy();
  if (addTask!=null&&!addTask.isCancelled()){ 
 addTask.cancel(); 
 }
}

(2)異步刪

private void deleteCat(final String id, final ImageView imageView){
 RealmAsyncTask deleteTask= mRealm.executeTransactionAsync(new Realm.Transaction() { 
@Override 
public void execute(Realm realm) { Cat cat=realm.where(Cat.class).equalTo("id",id).findFirst(); cat.deleteFromRealm(); } }, new Realm.Transaction.OnSuccess() {
 @Override 
public void onSuccess() { 
ToastUtil.showShortToast(mContext,"取消收藏成功"); } 
}, new Realm.Transaction.OnError() {
 @Override 
public void onError(Throwable error) {
 ToastUtil.showShortToast(mContext,"取消收藏失敗"); }
 }); }

最后在銷毀Activity或Fragment時,要取消掉異步任務

@Override 
protected void onDestroy() { 
super.onDestroy(); 
if (deleteTask!=null&&!addTask.isCancelled()){ 
deleteTask.cancel(); 
} 
}

(3)異步改

RealmAsyncTask updateTask= mRealm.executeTransactionAsync(new Realm.Transaction() { 
@Override 
public void execute(Realm realm) { Cat cat=realm.where(Cat.class).equalTo("id",mId).findFirst(); cat.setName(name); } }, new Realm.Transaction.OnSuccess() {
 @Override 
public void onSuccess() {
 ToastUtil.showShortToast(UpdateCatActivity.this,"更新成功"); } }, new Realm.Transaction.OnError() { 
@Override 
public void onError(Throwable error) { ToastUtil.showShortToast(UpdateCatActivity.this,"失敗成功"); 
} 
});

最后在銷毀Activity或Fragment時,要取消掉異步任務

@Override 
protected void onDestroy() {
 super.onDestroy(); 
if (updateTask!=null&&!addTask.isCancelled()){ 
updateTask.cancel(); 
}
 }

(4)異步查

RealmResults<Cat> cats=mRealm.where(Cat.class).findAllAsync(); cats.addChangeListener(new RealmChangeListener<RealmResults<Cat>>() { @Override 
public void onChange(RealmResults<Cat> element) { 
element= element.sort("id"); 
List<Cat> datas=mRealm.copyFromRealm(element); 
} 
});

最后在銷毀Activity或Fragment時,要取消掉異步任務

@Override 
protected void onDestroy() { 
super.onDestroy(); 
cats.removeChangeListeners();
 }            

我也是看著realm 的官方文檔自己理解寫出來的相關用法,如果有什么不對的地方希望大家一起討論一下。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內容