Realm資料庫使用
介紹
Realm是一個可以替代SQLite以及ORMlibraries的輕量級資料庫。
相比SQLite,Realm更快並且具有很多現代資料庫的特性,比如支援JSON,流式api,資料變更通知,以及加密支援
使用方法
1. 新增Realm到工程
要在安卓工程中使用Realm,你需要在module的build.gradle檔案中新增一個新增一個依賴:
compile 'io.realm:realm-android:0.84.1'
2. 建立一個Realm
一個Realm相當於一個SQLite資料庫。它有一個與之對應的檔案,一旦建立將持久儲存在安卓的檔案系統中,如下圖所示:
要建立一個新的Realm,你可以在任意Activity中呼叫靜態方法Realm.getInstance
Realm myRealm = Realm.getInstance(context);
注意,呼叫Realm.getInstance,而沒有傳入RealmConfiguration,會建立一個叫做 default.realm的Realm檔案。
如果你想向app中新增另一個Realm,必須使用一個RealmConfiguration.Builder物件,併為 Realm file 指定一個獨有的名字。
Realm myOtherRealm =
Realm.getInstance (
new RealmConfiguration.Builder(context)
.name("myOtherRealm.realm")
.build()
);
3. 建立一個RealmObject
只要繼承了RealmObject類,任意JavaBean都能儲存在Realm中。不知道JavaBean是什麼?它就是一個可序列化的java類,有預設構造器,成員變數有相應的getter/setter方法。比如,下面這個類的例項就能輕鬆的儲存在一個Realm中:
public class User extends RealmObject{
@PrimaryKey
private int id;
private String UserName;
private Double score;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
}
如果你想讓RealmObject的一個成員變數作為主鍵,你可以使用@PrimaryKey註解。比如,上面為User類新增一個主鍵id
4. 建立transaction
雖然從一個Realm讀取資料非常簡單(下一節有講),但是向它寫入資料就稍微複雜一點。Realm遵循 ACID (資料庫事務正確執行的四個基本要素的縮寫)規範,為了確保原子性和一致性,它強制所有的寫入操作都在一個事務中執行。
要開始一個新的事務,使用beginTransaction方法。類似地,要結束這個事務,使用commitTransaction方法。
User user = new User();
user.setId(Integer.parseInt(getTxtId().getText() + ""));
user.setUserName(getTxtUserName().getText() + "");
user.setScore(Double.parseDouble(getTxtScore().getText() + ""));
realm.beginTransaction();
realm.copyToRealmOrUpdate(user);
realm.commitTransaction();
5.Where查詢
Realm為建立查詢提供了一套非常直觀和流式的API。要建立一個查詢,使用相關Realm物件的where方法並傳入你感興趣的物件的類。建立完查詢之後,你可以使用返回一個RealmResults物件的findAll方法獲取所有的結果,findAll。在下面的例子中,我們獲取並列印Country的所有物件:
RealmResults<Country> results1 =
myRealm.where(Country.class).findAll();
for(Country c:results1) {
Log.d("results1", c.getName());
}
// Prints Norway, Russia
Realm提供了幾個命名非常貼切的方法,比如beginsWith, endsWith,lesserThan 和 greaterThan,可以用來過濾,篩選結果。下面的程式碼演示瞭如何使用greaterThan方法來獲取population(人口)大於1億的Countryobjects:
RealmResults<Country> results2 =
myRealm.where(Country.class)
.greaterThan("population", 100000000)
.findAll();
// Gets only Russia
如果你想查詢結果被歸類,你可以使用findAllSorted方法。在它的引數中,用一個String指定被歸類field的名字,並用一個boolean指定歸類順序。
// Sort by name, in descending order
RealmResults<Country> results3 =
myRealm.where(Country.class)
.findAllSorted("name", false);
// Gets Russia, Norway
Demo
DBUtils.java
public class DBUtils{
private volatile static DBUtils uniqueInstance;
public static DBUtils getInstance() {
if (uniqueInstance == null) {
synchronized (DBUtils.class) {
if (uniqueInstance == null) {
uniqueInstance = new DBUtils();
}
}
}
return uniqueInstance;
}
//新增,如果有主鍵且主鍵重複會報錯
public void save(Realm realm, RealmObject realmObject) {
realm.beginTransaction();
realm.copyToRealm(realmObject);
realm.commitTransaction();
}
//新增或修改,如果主鍵不存在則為新增,主鍵存在則修改
public void saveOrUpdate(Realm realm, RealmObject realmObject) {
realm.beginTransaction();
realm.copyToRealmOrUpdate(realmObject);
realm.commitTransaction();
}
//批量儲存或更新
public <T extends RealmObject> void saveList(Realm realm, List<T> realmObjects) {
realm.beginTransaction();
realm.copyToRealmOrUpdate(realmObjects);
realm.commitTransaction();
}
public <T extends RealmObject> T findFirst(Realm realm, Class<T> realmObjectClass) {
return realm.where(realmObjectClass).findFirst();
}
public <T extends RealmObject> RealmResults<T> findAll(Realm realm, Class<T> realmObjectClass) {
return realm.where(realmObjectClass).findAll();
}
//過濾查詢第一個
public <T extends RealmObject> T findFirstByField(Realm realm, String FiledName, String FieldValue, Class<T> realmObjectClass) {
return realm.where(realmObjectClass).equalTo(FiledName, FieldValue).findFirst();
}
//過濾查詢所有
public <T extends RealmObject> RealmResults<T> findAllByField(Realm realm, String FiledName, String FieldValue, Class<T> realmObjectClass) {
return realm.where(realmObjectClass).equalTo(FiledName, FieldValue).findAll();
}
//排序
public <T extends RealmObject> RealmResults<T> findAllDateSorted(Realm realm, String FieldName, Class<T> realmObjectClass) {
RealmResults<T> results = findAll(realm, realmObjectClass);
results.sort(FieldName, Sort.DESCENDING);
return results;
}
//刪除所有資料
public <T extends RealmObject> void clear(Realm realm, Class<T> realmObjectClass) {
realm.beginTransaction();
findAll(realm, realmObjectClass).clear();
realm.commitTransaction();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<ListView
android:id="@+id/mylist"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_weight="0.25"/>
<LinearLayout
android:id="@+id/bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/mylist"
android:orientation="vertical">
</LinearLayout>
<TableLayout
android:id="@+id/table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/mylist">
<TableRow>
<TextView
android:text="主鍵ID:"
android:layout_weight="1"
android:textSize="30sp"
android:layout_width="0dp"
android:layout_height="50dp"/>
<EditText
android:id="@+id/txtId"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="2"
android:inputType="number"/>
</TableRow>
<TableRow>
<TextView
android:text="使用者名稱:"
android:layout_weight="1"
android:textSize="30sp"
android:layout_width="0dp"
android:layout_height="50dp"/>
<EditText
android:id="@+id/txtUserName"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="50dp"/>
</TableRow>
<TableRow>
<TextView
android:text="成績:"
android:layout_weight="1"
android:textSize="30sp"
android:layout_width="0dp"
android:layout_height="50dp"/>
<EditText
android:id="@+id/txtScore"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="50dp"
android:inputType="numberDecimal"/>
</TableRow>
<TableRow>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新增或修改"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查詢第一個"/>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查詢所有"/>
</TableRow>
<TableRow>
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="排序"/>
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新增"/>
<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="刪除所有"/>
</TableRow>
</TableLayout>
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ListView myList;
private List<String> data;
private ArrayAdapter<String> adapter;
private Realm realm;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
User user = new User();
user.setId(Integer.parseInt(getTxtId().getText() + ""));
user.setUserName(getTxtUserName().getText() + "");
user.setScore(Double.parseDouble(getTxtScore().getText() + ""));
DBUtils.getInstance().saveOrUpdate(realm, user);
break;
case R.id.button2:
User user2 = DBUtils.getInstance().findFirst(realm, User.class);
if (user2 != null) {
data.clear();
data.add(user2.getId() + " " + user2.getUserName() + " " + user2.getScore());
adapter.notifyDataSetChanged();
}
break;
case R.id.button3:
List<User> users = DBUtils.getInstance().findAll(realm, User.class);
if (users !=null){
data.clear();
for(int i=0;i<users.size();i++){
User user3 = users.get(i);
data.add(user3.getId() + " " + user3.getUserName() + " " + user3.getScore());
}
adapter.notifyDataSetChanged();
}
break;
case R.id.button4:
RealmResults<User> users4 = DBUtils.getInstance().findAllDateSorted(realm, "score", User.class);
if (users4 !=null){
data.clear();
for(int i=0;i<users4.size();i++){
User user3 = users4.get(i);
data.add(user3.getId() + " " + user3.getUserName() + " " + user3.getScore());
}
adapter.notifyDataSetChanged();
}
break;
case R.id.button5:
User user5 = new User();
user5.setId(Integer.parseInt(getTxtId().getText() + ""));
user5.setUserName(getTxtUserName().getText() + "");
user5.setScore(Double.parseDouble(getTxtScore().getText() + ""));
DBUtils.getInstance().save(realm, user5);
break;
case R.id.button6:
DBUtils.getInstance().clear(realm, User.class);
data.clear();
adapter.notifyDataSetChanged();
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
realm = Realm.getInstance(this);
findViewById(R.id.button).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
findViewById(R.id.button3).setOnClickListener(this);
findViewById(R.id.button4).setOnClickListener(this);
findViewById(R.id.button5).setOnClickListener(this);
findViewById(R.id.button6).setOnClickListener(this);
myList = (ListView) findViewById(R.id.mylist);
data = new ArrayList<String>();
data.add("Hello World");
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
myList.setAdapter(adapter);
}
private EditText getTxtId() {
return (EditText) findViewById(R.id.txtId);
}
private EditText getTxtUserName() {
return (EditText) findViewById(R.id.txtUserName);
}
private EditText getTxtScore() {
return (EditText) findViewById(R.id.txtScore);
}
}