用于读写文件、读写数据库、网络信息交互等IO操作 .io() is backed by an unbounded thread-pool andis the sort of thing you'd use for non-computationally intensive tasks, that is stuff that doesn't put much load on the CPU. So yep interaction with the file system, interaction with databases or services on a different host are good examples. 创建一个用于IO操作的线程的调度器,内部实现机制是通过一个自动增长的线程池来实现的,这种机制可以用于异步操作阻塞IO工作,不要使用这个调度器来完成计算类工作,要完成计算类工作请使用computation()
.computation()
.computation() is backed by a bounded thread-pool with size equaltothenumberof available processors. If you tried to schedule cpu intensive work in parallel across more than the available processors (say using newThread()) then you are up for thread creation overhead and context switching overhead as threads vie for a processor andit's potentially a big performance hit. 这个调度器一般用于运行CPU密集型的计算任务,这些任务不会被IO等阻塞操作给阻塞,这个 Scheduler 使用大小为 CPU 核数的线程池来完成工作。同上面介绍的IO调度器一样,不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
.immediate()
Creates andreturns a Scheduler that executes work immediately on the current thread. 使用当前线程来完成任务,这是默认的 Scheduler。
.newThread()
Creates and returns a Scheduler that creates anew Thread foreach unit of work. 创建新线程,并在新线程执行操作。
.trampoline()
Creates andreturns a Scheduler that queues workon the current thread to be executed after the currentwork completes. 这种方式拥有一个队列,当我们想在当前线程执行一个任务,而是立即,我们可以先将这个任务存入队列,这个调度器将会按顺序运行队列中每一个任务。
Zip 允许接收多个事件源,并且将对应的事件通过一个方法处理后产生的结果添加到Observable中统一发布出去,这里需要注意的是最终的事件源个数取决于原始数据源中个数最少的那个,看下下面的例子: 事件源observable1 有20个事件,而observable2有10个事件,两个合成起来后最终产生的结果事件为10个。也就是最少的那个:
GitHubService service = restAdapter.create(GitHubService.class); List<Repo> repos = service.listRepos("octocat");
// Copy elements from Retrofit to Realm to persist them. realm.beginTransaction(); List<Repo> realmRepos = realm.copyToRealmOrUpdate(repos); realm.commitTransaction();
// A RealmObject that represents a city public class City extends RealmObject { private String city; privateint id; // getters and setters left out ... }
// Insert from a string realm.beginTransaction(); realm.createObjectFromJson(City.class, "{ city: \"Copenhagen\", id: 1 }"); realm.commitTransaction();
// Insert multiple items using a InputStream InputStream is = newFileInputStream(new File("path_to_file")); realm.beginTransaction(); try { realm.createAllFromJson(City.class, is); realm.commitTransaction(); } catch (IOException e) { realm.cancelTransaction(); }
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<RealmResults<Dog>>() { @Override public void onChange(RealmResults<Dog> puppies) { // ... 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<Dog>() { @Override public void onChange(Dog dog) { // ... 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(); } }
最后,这些监听器同样会在监听对象的引用对象改变时被触发,请见示例:
Person person = realm.where(Person.class).findFirst(); person.getDogs(); // => 2 - Assume there are 2 dogs in the list person.addChangeListener(new RealmChangeListener<Person>() { @Override public void onChange(Person person) { // 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.
RealmConfiguration config = new RealmConfiguration.Builder(context) .schemaVersion(2)// Must be bumped when the schema changes .migration(newMyMigration()) // Migration to run instead of throwing an exception .build()
// Example migration adding a new class RealmMigration migration = newRealmMigration() { @Override public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
// DynamicRealm exposes an editable schema RealmSchema schema = realm.getSchema();
// Migrate to version 1: Add a new class // Example: // public Person extends RealmObject { // private String name; // private int age; // // getters and setters left out for brevity // } if (oldVersion == 0) { schema.create("Person") .addField("name", String.class) .addField("age", int.class); oldVersion++; }
// Migrate to version 2: Add a primary key + object references // Example: // public Person extends RealmObject { // private String name; // @PrimaryKey // private int age; // private Dog favoriteDog; // private RealmList<Dog> dogs; // // getters and setters left out for brevity // } if (oldVersion == 1) { schema.get("Person") .addField("id", long.class, FieldAttribute.PRIMARY_KEY) .addRealmObjectField("favoriteDog", schema.get("Dog")) .addRealmListField("dogs", schema.get("Dog")); oldVersion++; } } }
// Assuming we had a person class with a @PrimaryKey on the 'id' field ... Intent intent = newIntent(getActivity(), ReceivingService.class); intent.putExtra("person_id", person.getId()); getActivity().startService(intent);
// in onCreate(), onHandleIntent(), etc. String personId = intent.getStringExtra("person_id"); Realm realm = Realm.getDefaultInstance(); Person person = realm.where(Person.class).equalTo("id", personId).findFirst(); // do something with the person ... realm.close();
privateclassDownloadOrdersextendsAsyncTask<Void, Void, Long>{ protectedLong doInBackground(Void... voids) { // Now in a background thread.
// Open the Realm Realm realm = Realm.getDefaultInstance(); // Work with Realm realm.createAllFromJson(Order.class, api.getNewOrders()); Order firstOrder = realm.where(Order.class).findFirst(); long orderId = firstOrder.getId(); // Id of order realm.close(); return orderId; }
protected void onPostExecute(Long orderId) { // Back on the Android mainThread // do something with orderId such as query Realm // for the order and perform some operation with it. } }
public classOrdersIntentServiceextendsIntentService{ public OrdersIntentService(String name) { super("OrdersIntentService"); }
@Override protected void onHandleIntent(Intent intent) { // Now in a background thread.
// Open the Realm Realm realm = Realm.getDefaultInstance(); // Work with Realm realm.createAllFromJson(Order.class, api.getNewOrders()); Order firstOrder = realm.where(Order.class).findFirst(); long orderId = firstOrder.getId(); // Id of order realm.close(); } }
对其它库的支持
GSON GSON 是 Google 开发的 JSON 处理库。GSON 与 Realm 可以无缝配合使用。
// Using the User class public classUserextendsRealmObject{ privateString name; privateString email; // getters and setters left out ... }
Gson gson = newGsonBuilder().create(); String json = "{ name : 'John', email : 'john@corporation.com' }"; User user = gson.fromJson(json, User.class);
GitHubService service = restAdapter.create(GitHubService.class); List<Repo> repos = service.listRepos("octocat");
// Copy elements from Retrofit to Realm to persist them. realm.beginTransaction(); List<Repo> realmRepos = realm.copyToRealmOrUpdate(repos); realm.commitTransaction();
RxJava
Realm 包含了对 RxJava 的原生支持。如下类可以被暴露为一个 Observable:Realm, RealmResults, RealmObject, DynamicRealm and DynamicRealmObject。
// Combining Realm, Retrofit and RxJava (Using Retrolambda syntax for brevity) // Load all persons and merge them with their latest stats from GitHub (if they have any) Realm realm = Realm.getDefaultInstance(); GitHubService api = retrofit.create(GitHubService.class); realm.where(Person.class).isNotNull("username").findAllAsync().asObservable() .filter(persons.isLoaded) .flatMap(persons -> Observable.from(persons)) .flatMap(person -> api.user(person.getGithubUserName()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(user -> showUser(user));
// Setup Realm in your Application public classMyApplicationextendsApplication{ @Override public void onCreate() { super.onCreate(); RealmConfiguration realmConfiguration = newRealmConfiguration.Builder(this).build(); Realm.setDefaultConfiguration(realmConfiguration); } }
// onCreate()/onDestroy() overlap when switching between activities so onCreate() // on Activity 2 will be called before onDestroy() on Activity 1. public classMyActivityextendsActivity{ privateRealm realm;
public classMyApplicationextendsApplication{ @Override public void onCreate() { super.onCreate(); // The realm file will be located in Context.getFilesDir() with name "default.realm" RealmConfiguration config = newRealmConfiguration.Builder(this).build(); Realm.setDefaultConfiguration(config); } }
MyObject obj = newMyObject(); 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();
RealmResults<User> result = realm.where(User.class).findAll(); result = result.sort("age"); // Sort ascending result = result.sort("age", Sort.DESCENDING);
final RealmResults<Dog> puppies = realm.where(Dog.class).lessThan("age", 2).findAll(); puppies.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() { @Override public void onChange(RealmResults<Dog> results) { // Queries are updated in real time puppies.size(); // => 1 } });
聚合 RealmResult 自带一些聚合方法:
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();
遍历查询结果:
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 ... }
异步查询
声明并注册回调方法:
private RealmChangeListener callback = new RealmChangeListener<RealmResults<User>>() { @Override publicvoidonChange(RealmResults<User> results) { // called once the query complete and on every update } };
publicvoidonStart() { RealmResults<User> result = realm.where(User.class).findAllAsync(); result.addChangeListener(callback); }
在退出 Activity 或者 Fragment 时移除监听器的注册以避免内存泄漏。
publicvoidonStop () { result.removeChangeListener(callback); // remove a particular listener // or result.removeChangeListeners(); // remove all registered listeners }
主动检查查询是否完成
RealmResults<User> result = realm.where(User.class).findAllAsync(); if (result.isLoaded()) { // Results are now available }
realm.executeTransactionAsync(new Realm.Transaction() { @Override publicvoidexecute(Realm realm) { // begin & end transcation calls are done for you Dog theDog = realm.where(Dog.class).equals("age", 1).findFirst(); theDog.setAge(3); } }, new Realm.Transaction.Callback() { @Override publicvoidonSuccess() { // Original Queries and Realm objects are automatically updated. puppies.size(); // => 0 because there are no more puppies (less than 2 years old) dog.getAge(); // => 3 the dogs age is updated } });
9. 删除数据
// 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.deleteFromRealm(0); results.deleteLastFromRealm(); // remove a single object Dog dog = results.get(5); dog.deleteFromRealm(); // Delete all matches results.deleteAllFromRealm(); realm.commitTransaction();
请注意第一个查询返回两个 User 对象,因为它们都满足查询条件。每个 User 对象都包含一个 Dog 对象列表——列表中至少有一个 Dog 对象满足查询条件。谨记我们是在寻找其拥有的 Dog 对象满足条件(name 和 color)的 User,不是在针对 Dog 对象进行查询。 因此第二个查询建立在第一个的 User 结果(r1)以及 r1 的每个 User 的 Dog 列表之上。两个 User 仍然满足第二个查询,但这次是 color 满足查询条件。
第一个查询表示找到所有的User他至少有一个Dog的名字为fluffy并且找到所有User他至少有一个Dog的颜色是brown 然后返回这两个结果的交集。 第二个查询表示找到所有的User他至少有一个Dog的名字为fluffy;然后在这个结果之上找到所有的User他至少有一个Dog的颜色为brown; 最后在之前的结果之上找到所有的 User 他至少有一个 Dog 的颜色为 yellow。
publicclass DogDeserialiser implements JsonDeserializer<Dog> { @Override public Dog deserialihttp://www.studytrails.com/java/json/java-google-json-custom-serializer-deserializer.jspze(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String name = json.getAsJsonObject().get("name").getAsString(); name = name.replace(" ", "_"); Dog dog = new Dog(name); return dog; } public static void main(String[] args) { String json = "{\"animal\":{\"name\":\"I am a dog\"}}"; Gson gson = new GsonBuilder().registerTypeAdapter(Dog.class, new DogDeserialiser()).create(); Type animalType = new TypeToken<Animal<Dog>>() { }.getType(); Animal<Dog> animal = gson.fromJson(json, animalType); System.out.println(animal.get().getName()); } }
JsonSerializer
public class DogSerializer implements JsonSerializer<dog> { @Override public JsonElement serialize(Dog src, Type typeOfSrc,JsonSerializationContext context) { // This method gets involved whenever the parser encounters the Dog // object (for which this serializer is registered) JsonObject object = newJsonObject(); String name = src.getName().replaceAll(" ", "_"); object.addProperty("name", name); // we create the json object for the dog and send it back to the // Gson serializer return object; } public static void main(String[] args) { Animall<Dog> animal = new Animall<Dog>(); Dog dog = newDog("I am a dog"); animal.setAnimal(dog); // Create the GsonBuilder and register a serializer for the Dog class. // Whenever the Dog class is encountered Gson calls the DogSerializer // we set pretty printing own to format the json Gson gson = newGsonBuilder().registerTypeAdapter(Dog.class, new DogSerializer()).setPrettyPrinting().create(); // Since Animal contains generic type create the type using TypeToken // class. Type animalType = new TypeToken<Animal<Dog>>() { }.getType(); System.out.println(gson.toJson(animal, animalType)); } }