文章目錄
Realm(Java)數據庫使用文檔(目錄)
Realm是移動設備數據庫的實例。 Realm可以是本地的或同步的。同步的Realm使用Realm Object Server透明地將其內容與其他設備同步。 當您的App像本地文件一樣繼續使用同步的Realm時,該Realm中的數據可能會被具有該Realm寫入權限的任何設備更新。 實際上,您的App可以與本地或同步的任何Realm相同的方式工作。
您是否要使用Realm 移動設備同步所有Realm數據庫?
所有與同步相關的文檔已移至我們的平臺文檔
有關Realm的更詳細討論,請閱讀 Realm數據模型。
2.1 初始化
通過實例化新的Realm
對象來打開Realm。 我們已經在示例中看到了這種用法:
// 初始化Realm
Realm.init(context);
// 獲取此線程的Realm實例
Realm realm = Realm.getDefaultInstance();
getDefaultInstance()
方法使用默認的RealmConfiguration
配置實例化Realm。
2.1.1 Realm配置
要控制Realm的創建方式,請使用RealmConfiguration對象。 Realm最基本配置爲:
RealmConfiguration config = new RealmConfiguration.Builder().build();
該配置(無選項)使用位於Context.getFilesDir
中的Realm文件default.realm
。 要使用其他配置,您需要創建一個新的RealmConfiguration
對象:
// 使用構建器模式創建RealmConfiguration。
// Realm文件將位於Context.getFilesDir()中,名稱爲“ myrealm.realm”
RealmConfiguration config = new RealmConfiguration.Builder()
.name("myrealm.realm")
.encryptionKey(getKey())
.schemaVersion(42)
.modules(new MySchemaModule())
.migration(new MyMigration())
.build();
// 使用配置
Realm realm = Realm.getInstance(config);
您可以具有多個RealmConfiguration對象,因此可以獨立控制每個Realm的版本,架構和位置。
RealmConfiguration myConfig = new RealmConfiguration.Builder()
.name("myrealm.realm")
.schemaVersion(2)
.modules(new MyCustomSchema())
.build();
RealmConfiguration otherConfig = new RealmConfiguration.Builder()
.name("otherrealm.realm")
.schemaVersion(5)
.modules(new MyOtherSchema())
.build();
Realm myRealm = Realm.getInstance(myConfig);
Realm otherRealm = Realm.getInstance(otherConfig);
通過使用Realm.getPath
獲取領域的絕對路徑。
重要的是要注意,Realm
實例是線程單例,這意味着靜態構造函數將響應來自給定線程的所有調用而返回相同的實例。
2.2.2 默認Realm
可以將RealmConfiguration
保存爲默認配置。 在自定義Application類中設置默認配置將使其在整個App中可用。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 默認的Realm文件在Context.getFilesDir();中爲“ default.realm”;
// 我們將其更改爲“ myrealm.realm”
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder().name("myrealm.realm").build();
Realm.setDefaultConfiguration(config);
}
}
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Realm realm = Realm.getDefaultInstance(); // 打開“ myrealm.realm”
try {
// ... Do something ...
} finally {
realm.close();
}
}
}
2.2 打開一個同步的Realm
您是否要使用Realm移動設備同步所有Realm數據庫?
所有與同步相關的文檔已移至我們的平臺文檔
2.3 只讀Realms
只讀僅在當前進程中強制執行。 其他進程或設備仍然有可能寫入只讀Realms。 同樣,針對只讀Realms的任何寫事務都會拋出IllegalStateException。這包括嘗試編寫模式,因此最初必須由其他來源提供。
在您的應用中附帶準備好的Realm文件有時會很有用-您可能希望將一些共享數據與您的應用捆綁在一起。 在很多情況下,您都不希望意外修改該Realm,因爲數據純粹是隻讀的。您可以通過在資產中捆綁Realm文件並使用只讀配置來做到這一點:
RealmConfiguration config = new RealmConfiguration.Builder()
.assetFile("my.realm")
.readOnly()
// 可選的,但是建議創建一個模塊來描述捆綁文件中的類。 否則,如果您的App包含文件中找不到的其他類,則由於無法以只讀模式更新架構,因此在打開Realm時它將崩潰。
.modules(new BundledRealmModule())
.build();
2.4 內存Realms
使用inMemory
配置,您可以創建一個完全在內存中運行而不會持久化到磁盤的Realm。
RealmConfiguration myConfig = new RealmConfiguration.Builder()
.name("myrealm.realm")
.inMemory()
.build();
如果內存不足,內存中的 Realm可能仍會使用磁盤空間,但是由內存中的 Realm創建的所有文件將在關閉Realm時被刪除。 不允許使用與永久性Realm相同的名稱創建內存中Realm-名稱仍然必須唯一。
當所有具有特定名稱的內存Realm實例超出範圍而沒有引用時,會釋放所有Realm的數據。 要在整個應用執行過程中保持內存中的“活動狀態”,請保留對其的引用。
2.5 動態Realms——DynamicRealm
在使用常規Realm
時,使用RealmObject
子類定義模型類。 關於類型安全性,這有很多好處。 但是有時,這些類型只有在運行時纔可用,例如,在遷移期間或使用CSV文件等基於字符串的數據時,就可以用DynamicRealm!
DynamicRealm是常規Realm的一種變體,它可以使用Realm數據而無需使用RealmObject
子類。 而是直接使用字符串而不是類來完成所有訪問。
打開DynamicRealm使用與常規Realm相同的配置,但是DynamicRealm會忽略任何已配置的架構,遷移和架構版本。
RealmConfiguration realmConfig = new RealmConfiguration.Builder().build();
DynamicRealm realm = DynamicRealm.getInstance(realmConfig);
// 在DynamicRealm中,所有對象都是DynamicRealmObjects
realm.beginTransaction();
DynamicRealmObject person = realm.createObject("Person");
realm.commitTransaction();
// 使用字符串訪問所有字段
String name = person.getString("name");
int age = person.getInt("age");
// 基礎架構仍然存在,因此訪問不存在的字段將引發異常
person.getString("I don't exist");
// 查詢仍然可以正常工作
RealmResults<DynamicRealmObject> persons = realm.where("Person")
.equalTo("name", "John")
.findAll();
DynamicRealm
以靈活性和性能爲代價獲得靈活性。 通常,您應該使用常規Realm。 僅在需要這種靈活性時才使用DynamicRealm。
2.6 關閉Realms
Realm
實現Closeable
來處理本機內存的重新分配和文件描述符,因此在使用完Realm實例後,請務必關閉它們。
Realm
實例是引用計數的-如果您在線程中兩次調用getInstance
,則也需要兩次調用close
。 這使您可以實現Runnable
類,而不必擔心哪個線程將執行它們:只需以getInstance
開頭並以close
結束即可。
對於UI線程,最簡單的方法是在擁有組件的onDestroy()
方法中執行realm.close
。 如果您需要創建UI以外的Looper
線程,則可以使用以下模式:
public class MyThread extends Thread {
private Realm realm;
@Override
public void run() {
Looper.prepare();
realm = Realm.getDefaultInstance();
try {
//... 使用Realm實例設置處理程序 ...
Looper.loop();
} finally {
realm.close();
}
}
}
對於AsyncTask
,這是一個很好的模式:
protected Void doInBackground(Void... params) {
Realm realm = Realm.getDefaultInstance();
try {
// ... Use the Realm instance ...
} finally {
realm.close();
}
return null;
}
如果你使用Thread
或Runnable
用於短期任務:
// Run a non-Looper thread with a Realm instance.
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Realm realm = Realm.getDefaultInstance();
try {
// ... Use the Realm instance ...
} finally {
realm.close();
}
}
});
thread.start();
如果您正在使用minSdkVersion> = 19
而且Java> = 7
的應用程序,則可以使用try-with-resources:
try (Realm realm = Realm.getDefaultInstance()) {
// 無需手動關閉Realm實例
}
2.7 自動刷新
如果從與Looper關聯的線程獲取Realm實例,則Realm實例將具有自動刷新功能。 (Android的UI線程是Looper。)這意味着Realm實例將定期更新爲最新版本。 這使您可以毫不費力地用最新內容不斷更新UI!
如果您從未附加Looper
的線程獲取Realm實例,則在調用waitForChange
方法之前,不會更新該實例中的對象。 保留舊版本的數據在內存和磁盤空間方面都很昂貴,並且隨着保留的版本和最新版本之間的版本數量增加,成本也會隨之增加。 這就是爲什麼在線程中完成Realm實例後立即關閉它很重要的原因。
如果要檢查您的Realm實例是否已激活自動刷新,請使用isAutoRefresh
方法。