前言:
Realm數(shù)據(jù)庫是基于C++編寫的一個不同于SQLite數(shù)據(jù)庫的數(shù)據(jù)庫引擎,是一個可以替代SQLite以及ORMlibraries的移動端數(shù)據(jù)庫。相比SQLite/ORMlibraries,Realm更輕量級,更快,并且具有很多現(xiàn)代數(shù)據(jù)庫的特性,支持JSON,流式api,數(shù)據(jù)變更通知,以及加密支持,這給android開發(fā)者提供了不少幫助。使用起來更是通俗易懂,簡單快捷。目前Realm最新版本是2.x,支持Java,Objective C,Swift,React-Native,tamarin五種編程方式,而下文所講內(nèi)容都是基于Realm2.x。通過介紹和使用本案例,學(xué)習(xí)和了解Realm的基本用法。
更多詳細(xì)介紹請參見官網(wǎng) :https://realm.io/
基本使用:
▲配置與導(dǎo)入
在項目Project的build.gradle文件中添加依賴:
在app的build文件加上:
在Application 中初始化,不配置也可以,就是默認(rèn)
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Realm.init(this);
//默認(rèn)配置
//RealmConfiguration configuration=new RealmConfiguration.Builder().build();
//自定義配置
RealmConfiguration configuration = new RealmConfiguration.Builder()
.name("donkor.realm")
.deleteRealmIfMigrationNeeded()
.build();
Realm.setDefaultConfiguration(configuration);
}
同時需要在AndroidManifest.xml中配置
▲案例介紹
圖書館管理系統(tǒng),其實說白了就是數(shù)據(jù)庫的增刪改查,本案例中的增刪改查只針對本地Realm的數(shù)據(jù)庫。Realm提供給我們的增刪改查操作足夠快,在UI線程中執(zhí)行操作就行。但是如果遇到較復(fù)雜的增刪改查,或操作的數(shù)據(jù)較多時,就可以子線程進(jìn)行操作,使用異步進(jìn)行增刪改查。案例分為兩個模塊,一個為學(xué)生管理,和圖書管理,而圖書管理則使用異步進(jìn)行增刪改查。
▲創(chuàng)建實體類
- 學(xué)生實體:有相應(yīng)的用戶名,密碼,姓名,多本收藏的圖書
- 圖書實體:有相應(yīng)的書名,作者,出版社
創(chuàng)建Student類繼承RealmObject
public class Student extends RealmObject {
//用來標(biāo)示主鍵
@PrimaryKey
private String name;
private long password;
private String nickname;
//一對多的關(guān)系
private RealmList<Book> books;
public RealmList<Book> getBooks() {
return books;
}
public void setBooks(RealmList<Book> books) {
this.books = books;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPassword() {
return password;
}
public void setPassword(long password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
創(chuàng)建Book類繼承RealmObject
public class Book extends RealmObject {
private String name;
private String author;
private String publishing;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublishing() {
return publishing;
}
public void setPublishing(String publishing) {
this.publishing = publishing;
}
}
※ 注: 同時必須知道的注解說明
@PrimaryKey
- 字段必須是String、 integer、byte、short、 int、long 以及它們的封裝類Byte, Short, Integer, and Long
- 使用了該注解之后可以使用copyToRealmOrUpdate()方法,通過主鍵查詢它的對象,如果查詢到了,則更新它,否則新建一個對象來代替。
- 使用了該注解將默認(rèn)設(shè)置(@index)注解
- 使用了該注解之后,創(chuàng)建和更新數(shù)據(jù)將會慢一點,查詢數(shù)據(jù)會快一點。
@Required
- 數(shù)據(jù)不能為null
@Ignore
- 忽略,即該字段不被存儲到本地
@Index
- 為這個字段添加一個搜索引擎,這將使插入數(shù)據(jù)變慢、數(shù)據(jù)增大,但是查詢會變快。建議在需要優(yōu)化讀取性能的情況下使用。
▲學(xué)生管理CRUD
一、增(添加學(xué)生)
可以使用事務(wù)操作或使用事務(wù)塊,兩種方法對數(shù)據(jù)庫進(jìn)行增加操作,同理,以下刪,改操作同樣可以使用以上兩種方法。而增添學(xué)生可以使用以下三種方式
1.新建一個對象,并進(jìn)行存儲
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
Student student = realm.createObject(Student.class);
student.setName("donkor");
student.setPassword(123456);
student.setNickname("aaa");
realm.commitTransaction();
2.復(fù)制一個對象到Realm數(shù)據(jù)庫
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
Student student=new Student();
student.setName("donkor");
student.setPassword(123456);
student.setNickname("aaa");
realm.copyToRealm(student);
realm.commitTransaction();
3.使用事務(wù)塊
Realm realm = Realm.getDefaultInstance();
final Student student = new Student();
student.setName("donkor");
student.setPassword(123456);
student.setNickname("aaa");
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealm(student);
}
});
而為學(xué)生添加多本圖書則可以使用以下兩種方式
//數(shù)據(jù)庫添加一本新書,同時為該同學(xué)添加該書
Book book = new Book();
book.setName("第一行代碼");
book.setAuthor("路人甲");
book.setPublishing("圖靈");
student.getBooks().add(book);
或者
//從數(shù)據(jù)庫中找到某一本書,添加給該同學(xué)
Book b=realm.where(Book.class).equalTo("name","第一行代碼").findFirst();
student.getBooks().add(b);
二、刪(刪除學(xué)生)
方法一使用事務(wù)操作
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
Student student = realm.where(Student.class).equalTo("name", "donkor").findFirst();
//指定student從數(shù)據(jù)庫中刪除
student.deleteFromRealm();
realm.commitTransaction();
方法二使用事務(wù)塊
final Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Student student=realm.where(Student.class).equalTo("name","donkor").findFirst();
//指定student從數(shù)據(jù)庫中刪除
student.deleteFromRealm();
}
});
※ 注:除了刪除指定某項數(shù)據(jù)時,還提供以下方法進(jìn)行刪除數(shù)據(jù)庫操作
RealmResults<Student> rrStudents = realm.where(Student.class).findAll();
//刪除第一個Student數(shù)據(jù)
rrStudents.deleteFirstFromRealm();
//刪除最后一個Student數(shù)據(jù)
rrStudents.deleteLastFromRealm();
//刪除位置為1的Student數(shù)據(jù)
//坐標(biāo)從0開始,0為第一項數(shù)據(jù),1為第二項
rrStudents.deleteFromRealm(1);
//刪除所有Student數(shù)據(jù)
rrStudents.deleteAllFromRealm();
三、改(修改學(xué)生)
方法一使用事務(wù)操作
Realm realm = Realm.getDefaultInstance();
Student student = realm.where(Student.class).equalTo("name", "donkor").findFirst();
realm.beginTransaction();
student.setName("newDonkor");
student.setPassword(132654);
student.setNickname("bbb");
realm.commitTransaction();
方法二使用事務(wù)塊
Realm realm = Realm.getDefaultInstance();
final Student student = realm.where(Student.class).equalTo("name", "donkor").findFirst();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
student.setName("newDonkor");
student.setPassword(132465);
student.setNickname("bbb");
}
});
四、查(查詢學(xué)生)
查詢?nèi)?/p>
Realm realm = Realm.getDefaultInstance();
//查詢?nèi)繉W(xué)生
RealmResults<Student> students = realm.where(Student.class).findAll();
//realm.copyFromRealm(students)方法將它轉(zhuǎn)為List<Student>
List<Student> studentList = realm.copyFromRealm(students);
條件查詢
Realm realm = Realm.getDefaultInstance();
//根據(jù)name查找第一個student信息
Student student = realm.where(Student.class).equalTo("name", "donkor").findFirst();
※ 注: 常用的條件查詢包括
- between(), greaterThan(), lessThan(), greaterThanOrEqualTo() 與 lessThanOrEqualTo()
- equalTo() 與 notEqualTo()
- contains()、beginsWith() 與 endsWith()
- isNull() 與 isNotNull()
- isEmpty() 與 isNotEmpty()
※ 注: 同時不僅支持對查詢結(jié)果的排序(默認(rèn)為升序排序),還支持聚合查詢,包括sum,min,max,average
▲圖書管理CRUD
一、異步增(添加圖書)
Realm realm = Realm.getDefaultInstance();
RealmAsyncTask addTask = realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Book book = new Book();
book.setName("第一行代碼");
book.setAuthor("郭霖");
book.setPublishing("圖靈");
realm.copyToRealm(book);
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
Toast.makeText(AddBookActivity.this, "Add success", Toast.LENGTH_SHORT).show();
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
Toast.makeText(AddBookActivity.this, "Add error", Toast.LENGTH_SHORT).show();
}
});
二、異步刪(刪除圖書)
Realm realm = Realm.getDefaultInstance();
RealmAsyncTask addTask = realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
//刪除指定圖書
Book book = realm.where(Book.class).equalTo("name", "donkor").findFirst();
book.deleteFromRealm();
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
Toast.makeText(AddBookActivity.this, "Delete success", Toast.LENGTH_SHORT).show();
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
Toast.makeText(AddBookActivity.this, "Delete error", Toast.LENGTH_SHORT).show();
}
});
三、異步改(修改圖書)
Realm realm = Realm.getDefaultInstance();
RealmAsyncTask addTask = realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
//刪改指定圖書
Book book = realm.where(Book.class).equalTo("name", "donkor").findFirst();
book.setName("第二行代碼");
book.setAuthor("郭霖");
book.setPublishing("圖靈");
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
Toast.makeText(AddBookActivity.this, "Update success", Toast.LENGTH_SHORT).show();
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
Toast.makeText(AddBookActivity.this, "Update error", Toast.LENGTH_SHORT).show();
}
});
※ 注: 以上異步增刪改操作在銷毀Activity或Fragment時,都不要忘記了要取消掉異步任務(wù)
@Override
protected void onDestroy() {
super.onDestroy();
//取消異步操作
if (addTask != null && !addTask.isCancelled()) {
addTask.cancel();
}
}
四、異步查(查詢圖書)
Realm realm = Realm.getDefaultInstance();
//查詢?nèi)繄D書
RealmResults<Book> books = realm.where(Book.class).findAllAsync();
books.addChangeListener(callback);
private RealmChangeListener callback = new RealmChangeListener() {
@Override
public void onChange(Object element) {
List<Book> bookList = realm.copyFromRealm(books);
BookAdapter bookAdapter = new BookAdapter(QueryBookActivity.this, bookList);
lvBooks.setAdapter(bookAdapter);
}
};
RealmChangeListener 在退出程序的時候要注銷監(jiān)聽
@Override
protected void onDestroy() {
super.onDestroy();
//注銷指定的監(jiān)聽
books.removeChangeListener(callback);
//注銷所有監(jiān)聽
books.removeChangeListeners();
}
最后看下我們實現(xiàn)了的功能和效果圖
github下載地址:https://github.com/ChenYXin/RealmDemo
關(guān)于我:
- Android開發(fā)交流QQ群:537891203
- 郵箱:donkor@yeah.net