Skip to content

Commit

Permalink
Add RxJava support
Browse files Browse the repository at this point in the history
  • Loading branch information
cmelchior committed Dec 17, 2015
1 parent 133235e commit d6db860
Show file tree
Hide file tree
Showing 41 changed files with 1,879 additions and 3 deletions.
2 changes: 2 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
0.87.0
* Added Realm.asObservable(), RealmResults.asObservable(), RealmObject.asObservable(), DynamicRealm.asObservable() and DynamicRealmObject.asObservable().
* Added RealmConfiguration.Builder.rxFactory() and RxObservableFactory for custom RxJava observable factory classes.
* Added Realm.copyFromRealm() for creating detached copies of Realm objects (#931).
* Added RealmObjectSchema.getFieldType() (#1883).
* Added unitTestExample to showcase unit and instrumentation tests. Examples include jUnit3, jUnit4, Espresso, Robolectric, and MPowermock usage with Realm (#1440).
Expand Down
2 changes: 1 addition & 1 deletion examples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ allprojects {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
classpath 'com.android.tools.build:gradle:1.5.0'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'
classpath 'com.novoda:gradle-android-command-plugin:1.3.0'
Expand Down
16 changes: 16 additions & 0 deletions examples/rxJavaExample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Examples combining RxJava and Realm

# Things to keep in mind

- Observables might have a default `Scheduler` they operate on that is different than the one
the RealmObject was created on. Accessing Realm objects on the wrong thread will throw an
`IllegalStateException`.

- RealmObjects are live objects that automatically stay up to date. Operators that expect
immutable objects will most likely not work as expected, e.g. `distinctUntilChanged`.

- Retrofit 1.x automatically uses a worker thread.

- Use the Realm async API instead of `subscribeOn` to move Realm work off the UI thread.

- You can use `Realm.copyFromRealm` to make a copy of Realm data.
34 changes: 34 additions & 0 deletions examples/rxJavaExample/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'android-command'
apply plugin: 'realm'

android {
compileSdkVersion rootProject.sdkVersion
buildToolsVersion rootProject.buildTools

defaultConfig {
applicationId 'io.realm.examples.rxjava'
targetSdkVersion rootProject.sdkVersion
minSdkVersion 15
versionCode 1
versionName "1.0"
}

buildTypes {
release {
minifyEnabled false
}
}

command {
events 2000
}
}

dependencies {
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
compile 'com.jakewharton.rxbinding:rxbinding:0.3.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
}
17 changes: 17 additions & 0 deletions examples/rxJavaExample/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/22.6.2/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
27 changes: 27 additions & 0 deletions examples/rxJavaExample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.realm.examples.rxjava" >

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:name=".MyApplication"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".animation.AnimationActivity" />
<activity android:name=".retrofit.RetrofitExample" />
<activity android:name=".throttle.ThrottleSearchActivity" />
<activity android:name=".gotchas.GotchasActivity" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.realm.examples.rxjava;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import java.util.Map;
import java.util.TreeMap;

import io.realm.examples.rxjava.animation.AnimationActivity;
import io.realm.examples.rxjava.gotchas.GotchasActivity;
import io.realm.examples.rxjava.retrofit.RetrofitExample;
import io.realm.examples.rxjava.throttle.ThrottleSearchActivity;

public class MainActivity extends Activity {

private ViewGroup container;
private TreeMap<String, Class<? extends Activity>> buttons = new TreeMap<String, Class<? extends Activity>>() {{
put("Animation", AnimationActivity.class);
put("Throttle search", ThrottleSearchActivity.class);
put("Network", RetrofitExample.class);
put("Working with Realm", GotchasActivity.class);
}};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
container = (ViewGroup) findViewById(R.id.list);
setupButtons();
}

private void setupButtons() {
for (final Map.Entry<String, Class<? extends Activity>> entry : buttons.entrySet()) {
Button button = new Button(this);
button.setText(entry.getKey());
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(entry.getValue());
}
});
container.addView(button);
}
}

private void startActivity(Class<? extends Activity> activityClass) {
startActivity(new Intent(this, activityClass));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.realm.examples.rxjava;

import android.app.Application;

import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.examples.rxjava.model.Person;

public class MyApplication extends Application {

private static MyApplication context;
private static TreeMap<String, String> testPersons = new TreeMap<>();
static {
testPersons.put("Chris", null);
testPersons.put("Christian", "cmelchior");
testPersons.put("Christoffer", null);
testPersons.put("Emanuele", "emanuelez");
testPersons.put("Dan", null);
testPersons.put("Donn", "donnfelker");
testPersons.put("Nabil", "nhachicha");
testPersons.put("Ron", null);
}

@Override
public void onCreate() {
super.onCreate();
context = this;
RealmConfiguration config = new RealmConfiguration.Builder(this).build();
Realm.deleteRealm(config);
Realm.setDefaultConfiguration(config);
createTestData();
}

// Create test data
private void createTestData() {
final Random r = new Random(42);
Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
for (Map.Entry<String, String> entry : testPersons.entrySet()) {
Person p = realm.createObject(Person.class);
p.setName(entry.getKey());
p.setGithubUserName(entry.getValue());
p.setAge(r.nextInt(100));
}
}
});
realm.close();
}

public static MyApplication getContext() {
return context;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.realm.examples.rxjava.animation;

import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.concurrent.TimeUnit;

import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.examples.rxjava.R;
import io.realm.examples.rxjava.model.Person;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.functions.Func2;

public class AnimationActivity extends Activity {

private Realm realm;
private Subscription subscription;
private ViewGroup container;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animations);
container = (ViewGroup) findViewById(R.id.list);
realm = Realm.getDefaultInstance();
}

@Override
protected void onResume() {
super.onResume();

// Load all persons and start inserting them with 1 sec. intervals.
// All RealmObject access has to be done on the same thread `findAllAsync` was called on.
// Warning: This example doesn't handle back pressure well.
subscription = realm.where(Person.class).findAllAsync().asObservable()
.flatMap(new Func1<RealmResults<Person>, Observable<Person>>() {
@Override
public Observable<Person> call(RealmResults<Person> persons) {
return Observable.from(persons);
}
})
.zipWith(Observable.interval(1, TimeUnit.SECONDS), new Func2<Person, Long, Person>() {
@Override
public Person call(Person person, Long tick) {
return person;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Person>() {
@Override
public void call(Person person) {
TextView personView = new TextView(AnimationActivity.this);
personView.setText(person.getName());
container.addView(personView);
}
});
}

@Override
protected void onPause() {
super.onPause();
subscription.unsubscribe();
}

@Override
protected void onDestroy() {
super.onDestroy();
realm.close();
}
}
Loading

0 comments on commit d6db860

Please sign in to comment.