Realm Java
2016-04-20 02:18
459 查看
Realm Java
当前这个翻译,主要是方便我自己查阅api,有很多地方写的比较晦涩或者没有翻译,敬请谅解
version 0.89.0
官方文档
Getting Started
Installation
工程的build.gradle中添加buildscript { repositories { jcenter() } dependencies { classpath "io.realm:realm-gradle-plugin:0.88.3" } }
引用module的build.gradle中添加
apply plugin: 'realm-android'
ProGuard
-keep class io.realm.annotations.RealmModule -keep @io.realm.annotations.RealmModule class * -keep class io.realm.internal.Keep -keep @io.realm.internal.Keep class * { *; } -dontwarn javax.** -dontwarn io.realm.**
Models
Realm支持类型
booleanbyte
short
int
long
float
double
String
Date
byte[]
RealmObject
RealmList
Required fields and null values
必须属性和null值在某些情况下,存在null值是不合理的.
@Required可以声明Boolean, Byte, Short, Integer, Long, Float, Double, String, byte[], Date,不能为null.
当其他类型使用@Required,会导致编译错误.
Fields with primitive types and the RealmList type are required implicitly.(必须通过setter和getter,否则不会获取到正确数据)
RealmObject不需要默认值
Ignoring properties
@Ignore来声明Realm忽略的属性Auto-Updating Objects
和ios一样顾名思义当一个数据的内容改变时,它会自动更新该数据的所有实例化对象
realm.beginTransaction(); Dog myDog = realm.createObject(Dog.class); myDog.setName("Fido"); myDog.setAge(1); realm.commitTransaction(); Dog myPuppy = realm.where(Dog.class).equals("age", 1).findFirst(); realm.beginTransaction(); myPuppy.setAge(2); realm.commitTransaction(); myDog.getAge(); // => 2
当数据变化,需要更新界面时,需要配合 [Realm notifications](#Realm notifications) 实现,后续会详细描述这功能
Indexed Properties
@Index 来修饰索引类型索引支持类型
String
byte
short
int
long
boolean
Date
注意事项(IOS的,Android没有说)
Indexing a property will greatly speed up queries where the property is compared for equality (i.e. the = and IN operators), at the cost of slower insertions.
使用索引增加查询速度的代价是插入数据时速度会降低
Primary Keys
@PrimaryKey 用来修饰主键.@PrimaryKey可以修饰String,short,int,long.@PrimaryKey只能修饰一个属性.
@PrimaryKey声明一个主键后,该属性会被隐性声明成@Index.
@PrimaryKey声明一个主键后,该属性会被隐性声明成@Required,不能为null.
声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。
一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。
当调用Realm.createObject(),它会返回一个有默认值的对象,当有主键时,主键会被设置默认值,这样可能会与已有对象冲突.所以最好使用copyToRealm()或者copyToRealmOrUpdate()替换
MyObject obj = new MyObject(); obj.setId(42); obj.setName("Fish"); realm.beginTransaction(); // This will create a new one in Realm // realm.copyToRealm(obj); // This will update a existing one with the same id or create a new one instead realm.copyToRealmOrUpdate(obj); realm.commitTransaction();
Ignored Properties
重写 Object.ignoredProperties() 可以防止 Realm 存储数据模型的某个属性。Realm 将不会干涉这些属性的常规操作,它们将由成员变量(ivar)提供支持,并且您能够轻易重写它们的 setter 和 getter。class Person: Object { dynamic var tmpID = 0 var name: String { // read-only properties are automatically ignored return "\(firstName) \(lastName)" } dynamic var firstName = "" dynamic var lastName = "" override static func ignoredProperties() -> [String] { return ["tmpID"] } }
Limitations
Realm不支持final,transient和volatile修饰Relationships
public class Email extends RealmObject { private String address; private boolean active; // ... setters and getters left out } public class Contact extends RealmObject { private String name; private Email email; // ... setters and getters left out }
一对一(To-One Relationships)
public class Contact extends RealmObject { private Email email; // Other fields… }
如果将email设为null,会断开2个实例间的关系,但是email实例没有被删除
一对多(To-Many Relationships)
class Person: Object { public class Contact extends RealmObject { private RealmList<Email> emails; // Other fields… } }
Link queries
public class Person extends RealmObject { private String id; private String name; private RealmList<Dog> dogs; // getters and setters } public class Dog extends RealmObject { private String id; private String name; private String color; // getters and setters }
// users => [U1,U2] RealmResults<User> users = realm.where(User.class) .equalTo("dogs.color", "Brown") .findAll();
// r1 => [U1,U2] RealmResults<User> r1 = realm.where(User.class) .equalTo("dogs.name", "Fluffy") .equalTo("dogs.color", "Brown") .findAll(); // r2 => [U2] RealmResults<User> r2 = realm.where(User.class) .equalTo("dogs.name", "Fluffy") .findAll() .where() .equalTo("dogs.color", "Brown") .findAll(); .where() .equalTo("dogs.color", "Yellow") .findAll();
Writes
所有写入操作(添加,修改,删除)都必须依托一个write transaction.由于write transaction会占用一定的资源,所以尽量精简write transaction的个数.当队列写入时,只需要一个就write transaction
在UI线程和后台线程同时开始写事务时,会导致ARN
写事务都是线程安全的.
// Obtain a Realm instance Realm realm = Realm.getDefaultInstance(); realm.beginTransaction(); //... add or update objects here ... realm.commitTransaction();
当开始写操作后,可以随时取消
realm.beginTransaction(); User user = realm.createObject(User.class); // ... realm.cancelTransaction();
Creating Objects
由于RealmObjects必须依赖在Realm,所以其创建方式如下:realm.beginTransaction(); User user = realm.createObject(User.class); // Create a new object user.setName("John"); user.setEmail("john@corporation.com"); realm.commitTransaction(); //========other User user = new User("John"); user.setEmail("john@corporation.com"); // Copy the object to Realm. Any further changes must happen on realmUser realm.beginTransaction(); User realmUser = realm.copyToRealm(user); realm.commitTransaction();
当使用realm.copyToRealm后,对原始数据修改,将不会被同步到Realm中.
Transaction blocks
会自动执行realm.beginTransaction(), realm.commitTransaction()realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { User user = realm.createObject(User.class); user.setName("John"); user.setEmail("john@corporation.com"); } });
Asynchronous Transactions
异步事务,主要是用于大量数据写入realm.executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm bgRealm) { User user = bgRealm.createObject(User.class); user.setName("John"); user.setEmail("john@corporation.com"); } }, new Realm.Transaction.OnSuccess() { @Override public void onSuccess() { // Transaction was a success. } }, new Realm.Transaction.OnError() { @Override public void onError(Throwable error) { // Transaction failed and was automatically canceled. } });
RealmAsyncTask transaction = realm.executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm bgRealm) { User user = bgRealm.createObject(User.class); user.setName("John"); user.setEmail("john@corporation.com"); } }, null); public void onStop () { if (transaction != null && !transaction.isCancelled()) { transaction.cancel(); } }
Queries
通过查询操作,Realm 将会返回包含 Object 集合的Results实例。Results 的表现和 List 十分相似。所有的查询(包括查询和属性访问)在 Realm 中都是延迟加载的,只有当属性被访问时,才能够读取相应的数据。也就是说当没有使用数据前,进行多次排序或者过滤都是不需要额外cpu时间的
查询结构不是Copy对象,而是引用对象.所以在Write操作中修改查询数据,是直接修改数据库中的数据.
Realm使用Fluent interface,也就是流接口
基本查询语句
// Build the query looking at all users: RealmQuery<User> query = realm.where(User.class); // Add query conditions: query.equalTo("name", "John"); query.or().equalTo("name", "Peter"); // Execute the query: RealmResults<User> result1 = query.findAll(); // Or alternatively do the same all at once (the "Fluent interface"): RealmResults<User> result2 = realm.where(User.class) .equalTo("name", "John") .or() .equalTo("name", "Peter") .findAll();
当查询内容为空时,RealmResults不会为null,它的size==0
Conditions
between, greaterThan(), lessThan(), greaterThanOrEqualTo() & lessThanOrEqualTo()equalTo() & notEqualTo()
contains(), beginsWith() & endsWith()
Logical Operators
主要是or()和not()not(),用来否定花括号中的条件
流接口中支持”花括号”,beginGroup() => ‘{’ , endGroup() => ‘}’
RealmResults<User> r = realm.where(User.class) .greaterThan("age", 10) //implicit AND .beginGroup() .equalTo("name", "Peter") .or() .contains("name", "Jo") .endGroup() .findAll();
Sorting
RealmResults<User> result = realm.where(User.class).findAll(); result.sort("age"); // Sort ascending result.sort("age", Sort.DESCENDING);
Chaining Queries
RealmResults<User> teenagers = realm.where(User.class).between("age", 13, 20).findAll(); User firstJohn = teenagers.where().equalTo("name", "John").findFirst(); RealmResults<User> teensWithPups = realm.where(User.class).between("age", 13, 20).equalTo("dogs.age", 1).findAll();
Auto-Updating Results
结果会自动更新RealmResults<Dog> puppies = realm.where(Dog.class).lessThan("age", 2).findAll(); puppies.size(); // => 0 realm.beginTransaction(); Dog dog = realm.createObject(Dog.class); dog.setName("Fido"); dog.setAge(1); realm.commitTransaction(); puppies.size(); // => 1
Retrieving objects by type
realm.allObjects()Aggregation
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();
Iterations
RealmResults<User> results = realm.where(User.class).findAll(); for (User u : results) { // ... do something with the object ... } RealmResults<User> results = realm.where(User.class).findAll(); for (int i = 0; i < results.size(); i++) { User u = results.get(i); // ... do something with the object ... } // Find all dogs older than or equal to 2 and change their age to 1 RealmResults results = realm.where(Dog.class).greaterThanOrEqualTo("age", 2).findAll(); realm.beginTransaction(); for (int i = results.size() -1; i >=0; i--) { results.get(i).setAge(1); } realm.commitTransaction();
Deletion
// obtain the results of a query RealmResults<Dog> results = realm.where(Dog.class).findAll(); // All changes to data must happen in a transaction realm.beginTransaction(); // remove single match results.remove(0); results.removeLast(); // remove a single object Dog dog = results.get(5); dog.removeFromRealm(); // Delete all matches results.clear(); realm.commitTransaction()
Asynchronous Queries
private RealmChangeListener callback = new RealmChangeListener() { @Override public void onChange() { // called once the query complete and on every update // use the result } }; public void onStart() { RealmResults<User> result = realm.where(User.class).findAllAsync(); result.addChangeListener(callback); } public void onStop () { result.removeChangeListener(callback); // remove a particular listener // or result.removeChangeListeners(); // remove all registered listeners }
Check if the query has completed
当RealmResults有数据绑定后,result.isLoaded(),会一直返回true
RealmResults<User> result = realm.where(User.class).findAllAsync(); if (result.isLoaded()) { // Results are now available }
Force load an asynchronous query
强制执行异步查询,会阻塞当前线程.
RealmResults<User> result = realm.where(User.class).findAllAsync(); result.load() // be careful, this will block the current thread until it returns
Non-Looper threads
异步查询只能使用在有Looper的线程上,否则会抛出异常.
Realms
Realm Configuration
Realm.setDefaultConfiguration()直接设置默认配置Realm默认会将文件存储在Context.getFilesDir(),文件路径是无法修改的
// The RealmConfiguration is created using the builder pattern. // The realm file will be located in Context.getFilesDir() with name "myrealm.realm" RealmConfiguration config = new RealmConfiguration.Builder(context) .name("myrealm.realm") .encryptionKey(getKey()) .schemaVersion(42) .setModules(new MySchemaModule()) .migration(new MyMigration()) .build(); // Use the config Realm realm = Realm.getInstance(config); RealmConfiguration myConfig = new RealmConfiguration.Builder(context) .name("myrealm.realm"). .schemaVersion(2) .setModules(new MyCustomSchema()) .build(); RealmConfiguration otherConfig = new RealmConfiguration.Builder(context) .name("otherrealm.realm") .schemaVersion(5) .setModules(new MyOtherSchema()) .build(); Realm myRealm = Realm.getInstance(myConfig); Realm otherRealm = Realm.getInstance(otherConfig);
The Default RealmConfiguration
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // The realm file will be located in Context.getFilesDir() with name "default.realm" RealmConfiguration config = new RealmConfiguration.Builder(this).build(); Realm.setDefaultConfiguration(config); } } public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Realm realm = Realm.getDefaultInstance(); // ... Do something ... realm.close(); } }
In-Memory Realms
内存中的Realms,没有保存在磁盘上.优点:可以快速的访问数据,而不需要考虑数据持久化的性能开销.内存Realms只会在temp路径里存放几个文件,用来进行线程间数据同步,不会将Realms中任何数据写入磁盘中
Dynamic Realms
不需要建立基于RealmObject类,只需要通过字符串来操作.主要优势是灵活
RealmConfiguration realmConfig = new RealmConfiguration.Builder(context).build(); DynamicRealm realm = DynamicRealm.getInstance(realmConfig); // In a DynamicRealm all objects are DynamicRealmObjects DynamicRealmObject person = realm.createObject("Person"); // All fields are accesssed using strings String name = person.getString("name"); int age = person.getInt("age"); // An underlying schema still exists, so accessing a field that does not exist // will throw an exception person.getString("I don't exist"); // Queries stil work normally RealmResults<DynamicRealmObject> persons = realm.where("Person") .equalTo("name", "John") .findAll();
Closing Realm instances
protected Void doInBackground(Void... params) { Realm realm = null; try { realm = Realm.getDefaultInstance(); // ... Use the Realm instance } finally { if (realm != null) { realm.close(); } } return null; }
在有Looper的线程中,应该如下使用:
public class MyThread extends Thread { private Realm realm; public void run() { Looper.prepare(); try { realm = Realm.getDefaultInstance(); //... Setup the handlers using the Realm instance Lopper.loop(); } finally { if (realm != null) { realm.close(); } } } }
在minSdkVersion >= 19时,可以如下使用:
try (Realm realm = Realm.getDefaultInstance()) { // No need to close the Realm instance manually }
Auto-Refresh
在有Looper的线程上(包括UI线程)会自动更新.可以使用isAutoRefresh()来知晓是否当前Realm是否支持自动刷新
Threading
这一章主要是讲多线程开发,大量写入事务最好是放在其他线程中,以防止UI线程被阻塞只在一个线程中处理所有事情,不需要担心并发和多线程.(然并卵的话)
Realm在多线程处理上不需要使用线程锁,只需要注意写入操作需要在Write事件中.
Realm Threading Example
// in a Fragment or Activity, etc @Override public void onActivityCreated(Bundle savedInstanceState) { // ... boilerplate omitted for brevity realm = Realm.getDefaultInstance(); // get all the customers RealmResults<Customer> customers = realm.where(Customer.class).findAllAsync(); // ... build a list adapter and set it to the ListView/RecyclerView/etc // set up a Realm change listener changeListener = new RealmChangeListener() { @Override public void onChange() { // This is called anytime the Realm database changes on any thread. // Please note, change listeners only work on Looper threads. // For non-looper threads, you manually have to use Realm.refresh() instead. listAdapter.notifyDataSetChanged(); // Update the UI } }; // Tell Realm to notify our listener when the customers results // have changed (items added, removed, updated, anything of the sort). customers.addChangeListener(changeListener); } // In a background service, in another thread public class PollingService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Realm realm = Realm.getDefaultInstance(); // go do some network calls/etc and get some data and stuff it into a 'json' var String json = customerApi.getCustomers(); realm.beginTransaction(); realm.createObjectFromJson(Customer.class, json); // Save a bunch of new Customer objects realm.commitTransaction(); // At this point, the data in the UI thread is already up to date. // ... } // ... }
Using a Realm across Threads
在UI线程或者其他添加Runloop的线程上,Realm都会自动更新其他线程Runloop的操作结果.([b]这里是说其他线程有更新,UI线程或Runloop线程都不会更新数据)[/b]
在其他类型的线程上操作,都是基于Snapshots.
UI线程或者其他添加Runloop的线程上,数据都会自动刷新,除非将Realm.autorefresh设置为NO
其他类型的线程,都是以最后一次修改成功的Realm为snapshot,除非是手动refresh
Realm, RealmObject or RealmResults不能进行多线程传递.
最好使用asynchronous query和asynchronous transaction
``` ##Schemas 可以让Realm只包含特定类型.
// Create the module
@RealmModule(classes = { Person.class, Dog.class })
public class MyModule {
}
// Set the module in the RealmConfiguration to allow only classes defined by the module.
RealmConfiguration config = new RealmConfiguration.Builder(context)
.setModules(new MyModule())
.build();
// It is possible to combine multiple modules to one schema.
RealmConfiguration config = new RealmConfiguration.Builder(context)
.setModules(new MyModule(), new MyOtherModule())
.build();
###Sharing schemas ```基于Library开发时,需要注意Realm必须expose并且Realm必须设置对应的schema. 如果不设置schema,当你使用它们时,会抛出异常. <div class="se-preview-section-delimiter"></div>
// Library must create a module and set library = true. This will prevent the default // module from being created. // allClasses = true can be used instead of listing all classes in the library. @RealmModule(library = true, allClasses = true) public class MyLibraryModule { } // Library projects are therefore required to explicitly set their own module. RealmConfiguration libraryConfig = new RealmConfiguration.Builder(context) .name("library.realm") .setModules(new MyLibraryModule()) .build(); // Apps can add the library RealmModule to their own schema. RealmConfiguration config = new RealmConfiguration.Builder(context) .name("app.realm") .setModules(Realm.getDefaultModule(), new MyLibraryModule()) .build(); <div class="se-preview-section-delimiter"></div>
JSON
支持导入类型String,JSONObject,JSONArray和InputStream.// A RealmObject that represents a city public class City extends RealmObject { private String city; private int id; // getters and setters left out ... } // Insert from a string realm.beginTransaction(); realm.createObjectFromJson(City.class, "{ city: \"Copenhagen\", id: 1 }"); realm.commitTransaction(); // Insert from a JSONObject realm.beginTransaction(); realm.createObjectFromJson(City.class, jsonObject); realm.commitTransaction(); // Insert from a JSONArray realm.beginTransaction(); realm.createObjectFromJson(City.class, jsonArray); realm.commitTransaction(); // Insert multiple items using a InputStream InputStream is = new FileInputStream(new File("path_to_file")); realm.beginTransaction(); try { realm.createAllFromJson(City.class, is); realm.commitTransaction(); } catch (IOException e) { realm.cancelTransaction(); } <div class="se-preview-section-delimiter"></div>
注意事项
使用JSON创建对象属性为null值
没有用@Required修饰的会被赋值null
用@Required的会抛出异常
使用JSON更新对象属性为null值
没有用@Required修饰的会被赋值null
用@Required的会抛出异常
JSON没有属性对应的字段
Leave the value unchanged for both required and not-required fields.(意思好像是,不会改变其原值,没有具体说是创建还是更新)
Notifications
修改Listeners只会在有Looper的线程(包含UI线程)中回调,其他线程只能使用Realm.refresh()来刷新在多线程中修改数据,有Looper的线程(包含UI线程)都会收到Listeners的回调
public class MyActivity extends Activity { private Realm realm; // A reference to RealmChangeListener needs to be held to avoid being // removed by the garbage collector. private RealmChangeListener realmListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); realm = Realm.getDefaultInstance(); reamlListener = new RealmChangeListener() { @Override public void onChange() { // ... do something with the updates (UI, etc.) ... }}; realm.addChangeListener(realmListener); } @Override protected void onDestroy() { super.onDestroy(); // Remove the listener. realm.removeChangeListener(realmListener); // Close the realm instance. realm.close(); } } <div class="se-preview-section-delimiter"></div>
关闭所有Listeners
realm.removeAllChangeListeners(); <div class="se-preview-section-delimiter"></div>
RealmObject和RealmResults都可以添加Listeners
public class MyActivity extends Activity { private Realm realm; private RealmChangeListener puppiesListener; private RealmChangeListener dogListener; private RealmResults<Dog> puppies; private Dog dog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); realm = Realm.getDefaultInstance(); puppiesListener = new RealmChangeListener() { @Override public void onChange() { // ... do something with the updated puppies instance }}; // Find all the puppies puppies = realm.where(Dog.class).lessThanOrEqualTo("age", 2).findAll(); puppies.addChangeListener(puppiesListener); dogListener = new RealmChangeListener() { @Override public void onChange() { // ... do something with the updated Dog instance }}; dog = realm.where(Dog.class).equals("name", "Fido").findFirst(); dog.addChangeListener(dogListener); } @Override protected void onDestroy() { super.onDestroy(); // Remove the listeners puppies.removeChangeListener(puppiesListener); dog.removeChangeListener(dogListener); // Close the realm instance. realm.close(); } } <div class="se-preview-section-delimiter"></div>
给类添加Listeners
Person person = realm.where(Person.class).findFirst(); person.getDogs(); // => 2 - Assume there are 2 dogs in the list person.addChangeListener(new RealmChangeListener() { @Override public void onChange() { // React to the change in the Person instance. // This will also get called when any referenced dogs are updated. } }); Dog dog = person.getDogs().get(0); realm.beginTransaction(); dog.setAge(5); realm.commitTransaction(); // Person change listener is called on the next iteration of the run loop because // a referenced dog object changed. <div class="se-preview-section-delimiter"></div>
Migrations
数据迁移,版本迭代时,数据库常用为什么要进行数据库迁移(借用Swift)
class Person: Object { dynamic var firstName = "" dynamic var lastName = "" dynamic var age = 0 } <div class="se-preview-section-delimiter"></div>
在某个版本更新中,变成了下边这样
class Person: Object { dynamic var fullName = "" dynamic var age = 0 } <div class="se-preview-section-delimiter"></div>
那么就需要用到数据迁移了.
Linear Migrations
需要考虑跨版本的数据库迁移,例如v0直接升级到v3版本,而不是只考虑v2升级到v3.// Example migration adding a new class RealmMigration migration = new RealmMigration() { @Override public void migrate(DynamicRealm realm, long oldVersion, long newVersion) { // During a migration, a DynamicRealm is exposed. A DynamicRealm is an untyped variant of a normal Realm, but // with the same object creation and query capabilities. // A DynamicRealm uses Strings instead of Class references because the Classes might not even exist or have been // renamed. // Access the Realm schema in order to create, modify or delete classes and their fields. RealmSchema schema = realm.getSchema(); /************************************************ // Version 0 class Person @Required String firstName; @Required String lastName; int age; // Version 1 class Person @Required String fullName; // combine firstName and lastName into single field. int age; ************************************************/ // Migrate from version 0 to version 1 if (oldVersion == 0) { RealmObjectSchema personSchema = schema.get("Person"); // Combine 'firstName' and 'lastName' in a new field called 'fullName' personSchema .addField("fullName", String.class, FieldAttribute.REQUIRED) .transform(new RealmObjectSchema.Function() { @Override public void apply(DynamicRealmObject obj) { obj.set("fullName", obj.getString("firstName") + " " + obj.getString("lastName")); } }) .removeField("firstName") .removeField("lastName"); oldVersion++; } /************************************************ // Version 2 class Pet // add a new model class @Required String name; @Required String type; class Person @Required String fullName; int age; RealmList<Pet> pets; // add an array property ************************************************/ // Migrate from version 1 to version 2 if (oldVersion == 1) { // Create a new class RealmObjectSchema petSchema = schema.create("Pet") .addField("name", String.class, FieldAttribute.REQUIRED) .addField("type", String.class, FieldAttribute.REQUIRED); // Add a new field to an old class and populate it with initial data schema.get("Person") .addRealmListField("pets", petSchema) .transform(new RealmObjectSchema.Function() { @Override public void apply(DynamicRealmObject obj) { if (obj.getString("fullName").equals("JP McDonald")) { DynamicRealmObject pet = realm.createObject("Pet"); pet.setString("name", "Jimbo"); pet.setString("type", "dog"); obj.getList("pets").add(pet); } } }); oldVersion++; } /************************************************ // Version 3 class Pet @Required String name; int type; // type becomes int class Person String fullName; // fullName is nullable now RealmList<Pet> pets; // age and pets re-ordered (no action needed) int age; ************************************************/ // Migrate from version 2 to version 3 if (oldVersion == 2) { RealmObjectSchema personSchema = schema.get("Person"); personSchema.setNullable("fullName", true); // fullName is nullable now. // Change type from String to int schema.get("Pet") .addField("type_tmp", int.class) .transform(new RealmObjectSchema.Function() { @Override public void apply(DynamicRealmObject obj) { String oldType = obj.getString("type"); if (oldType.equals("dog")) { obj.setLong("type_tmp", 1); } else if (oldType.equals("cat")) { obj.setInt("type_tmp", 2); } else if (oldType.equals("hamster")) { obj.setInt("type_tmp", 3); } } }) .removeField("type") .renameField("type_tmp", "type"); oldVersion++; } } <div class="se-preview-section-delimiter"></div>
Encryption
Realm的加密方式为:key为64字节,AES-256加密过的 Realm 只会带来很少的额外资源占用(通常最多只会比平常慢10%)
注:如果数据库加密后,由于不知道加密方式,即使有原始key,也无法获取解密key,所以无法用Realm Browser查看.
注:如果数据库加密,每次获取Realm实例时,必须使用encryptionKey.
byte[] key = new byte[64]; new SecureRandom().nextBytes(key); RealmConfiguration config = new RealmConfiguration.Builder(context) .encryptionKey(key) .build(); Realm realm = Realm.getInstance(config); <div class="se-preview-section-delimiter"></div>
Other Libraries
GSON
GSON is a library created by Google for deserializing and serializing JSON. When using Realm with GSON 2.3.1 (latest version), you have to specify an ExclusionStrategy.// Using the User class public class User extends RealmObject { private String name; private String email; // getters and setters left out ... } Gson gson = new GsonBuilder() .setExclusionStrategies(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { return f.getDeclaringClass().equals(RealmObject.class); } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } }) .create(); String json = "{ name : 'John', email : 'john@corporation.com' }"; User user = gson.fromJson(json, User.class); <div class="se-preview-section-delimiter"></div>
Retrofit
Retrofit 1.*
uses GSON internally, it also needs a properly configured GsonConverter if you want to deserialize network JSON data to RealmObjects.Gson gson = new GsonBuilder() .setExclusionStrategies(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { return f.getDeclaringClass().equals(RealmObject.class); } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } }) .create(); // Configure Retrofit to use the proper GSON converter RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://api.github.com") .setConverter(new GsonConverter(gson)) .build(); GitHubService service = restAdapter.create(GitHubService.class); <div class="se-preview-section-delimiter"></div>
Retrofit 2.*
With Retrofit 2, GSON is no longer used by default, but can be used via its converter module.dependencies { compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3' compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3' <div class="se-preview-section-delimiter"></div>
Gson gson = new GsonBuilder() .setExclusionStrategies(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { return f.getDeclaringClass().equals(RealmObject.class); } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } }) .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .addConverterFactory(GsonConverterFactory.create(gson) .build();
相关文章推荐
- java的web基础笔试题
- Spring MVC 3.x 和 JDK8不兼容
- web day12 JSP三大指令,九个内置对象,动作标签,JavaBean(包含内省),EL表达式,函数库
- java基础笔试题
- (22)Spring Boot 拦截器HandlerInterceptor【从零开始学Spring Boot】
- Spring.Net的AOP的通知
- (21)Spring Boot过滤器、监听器【从零开始学Spring Boot】
- Java界面设计的用途
- Spring.Net的IOC入门
- Java-单机版的书店管理系统(练习设计模块和思想_系列 八 )
- Java-单机版的书店管理系统(练习设计模块和思想_系列 八 )
- (20)Spring Boot Servlet【从零开始学Spring Boot】
- 关于java字符串编译优化问题
- thinkeing in java--java中的基本对象类型及其如何存储
- Java线程安全
- spring与hibernate整合之:继承HibernateDAOSupport方式+理解xml与AutoWired、Resource的区别
- java concurrency
- (19)Spring Boot 添加JSP支持【从零开始学Spring Boot】
- 马士兵JAVA基础实录教程
- 学习Spring(六) -- Spring中Bean的作用域以及生命周期