Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for android-lifecycle #216

Merged
merged 5 commits into from
May 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ You have a few options for that:

1. Use rxlifecycle-components and subclass the provided `RxActivity`, `RxFragment`, etc. classes.
1. Use [Navi](https://github.com/trello/navi/) + rxlifecycle-navi to generate providers.
1. Use [Android's lifecycle](https://developer.android.com/topic/libraries/architecture/lifecycle.html) + rxlifecycle-android-lifecycle to generate providers.
1. Write the implementation yourself.

If you use rxlifecycle-components, just extend the appropriate class, then use the built-in `bindToLifecycle()` (or `bindUntilEvent()`) methods:
Expand Down Expand Up @@ -79,6 +80,23 @@ public class MyActivity extends NaviActivity {
}
```

If you use rxlifecycle-android-lifecycle, then you just pass your `LifecycleOwner` to `AndroidLifecycle` to generate a provider:

```java
public class MyActivity extends LifecycleActivity {
private final LifecycleProvider<Lifecycle.Event> provider
= AndroidLifecycle.createLifecycleProvider(this);

@Override
public void onResume() {
super.onResume();
myObservable
.compose(provider.bindToLifecycle())
.subscribe();
}
}
```

## Unsubscription

RxLifecycle does not actually unsubscribe the sequence. Instead it terminates the sequence. The way in which
Expand All @@ -94,7 +112,7 @@ the `Subscription` yourself and call `unsubscribe()` when appropriate.

The rxlifecycle-kotlin module provides built-in extensions to the base RxJava types:

```java
```kotlin
myObservable
.bindToLifecycle(myView)
.subscribe { }
Expand All @@ -104,6 +122,16 @@ myObservable
.subscribe { }
```

There is an additional rxlifecycle-android-lifecycle-kotlin module to provider extensions to work
with `LivecycleOwner`'s.

```kotlin

myObservable
.bindToLifecycle(myLifecycleActivity, ON_STOP)
.subscribe { }
```

## Installation

```gradle
Expand All @@ -118,8 +146,14 @@ compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'
// If you want to use Navi for providers
compile 'com.trello.rxlifecycle2:rxlifecycle-navi:2.0.1'

// If you want to use Android Lifecycle for providers
compile 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.0.1'

// If you want to use Kotlin syntax
compile 'com.trello.rxlifecycle2:rxlifecycle-kotlin:2.0.1'

// If you want to use Kotlin syntax with Android Lifecycle
compile 'com.trello.rxlifecycle2:rxlifecycle-android-kotlin:2.0.1'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking from previous experience, we should make a comment here that it's unreleased (or just remove this altogether). Otherwise people will start trying to use it before we release.

```

## License
Expand Down
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0-rc1'
classpath 'com.android.tools.build:gradle:2.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$verKotlin"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$verKotlin"
classpath 'com.github.ben-manes:gradle-versions-plugin:0.14.0'
Expand All @@ -30,6 +30,7 @@ ext {
buildToolsVersion = '25'

supportLibVersion = '25.2.0'
lifecycleVersion = '1.0.0-alpha1'

sourceCompatibilityVersion = JavaVersion.VERSION_1_7
targetCompatibilityVersion = JavaVersion.VERSION_1_7
Expand All @@ -38,6 +39,8 @@ ext {
rxJava = 'io.reactivex.rxjava2:rxjava:2.0.6'
rxAndroid = 'io.reactivex.rxjava2:rxandroid:2.0.1'
navi = 'com.trello.navi2:navi:2.0'
lifecycle = "android.arch.lifecycle:runtime:$lifecycleVersion"
lifecycleProcessor = "android.arch.lifecycle:compiler:$lifecycleVersion"
kotlinStdlib = "org.jetbrains.kotlin:kotlin-stdlib:$verKotlin"
appCompat = "com.android.support:appcompat-v7:$supportLibVersion"
supportAnnotations = "com.android.support:support-annotations:$supportLibVersion"
Expand Down
1 change: 1 addition & 0 deletions rxlifecycle-android-lifecycle-kotlin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
26 changes: 26 additions & 0 deletions rxlifecycle-android-lifecycle-kotlin/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'kotlin-android'

android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion

defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
}
}

repositories {
mavenCentral()
maven { url 'https://maven.google.com' }
}

dependencies {
compile kotlinStdlib
compile project(':rxlifecycle-android-lifecycle')
}

apply from: "$rootDir/gradle/artifacts.gradle"
apply from: "$rootDir/gradle/gradle-mvn-push.gradle"

4 changes: 4 additions & 0 deletions rxlifecycle-android-lifecycle-kotlin/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_NAME=RxLifecycle-Andoird-Lifecycle-kotlin
POM_DESCRIPTION=RxLifecycle-Android-Lifecycle-kotlin
POM_ARTIFACT_ID=rxlifecycle-android-lifecycle-kotlin
POM_PACKAGING=aar
25 changes: 25 additions & 0 deletions rxlifecycle-android-lifecycle-kotlin/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /opt/android-sdk/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 *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="me.tatarka.rxlifecycle_android_lifecycle_kotlin" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* 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 com.trello.rxlifecycle2.android.lifecycle.kotlin

import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleOwner
import com.trello.lifecycle2.android.lifecycle.AndroidLifecycle
import io.reactivex.*

fun <T> Observable<T>.bindToLifecycle(owner: LifecycleOwner): Observable<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindToLifecycle())

fun <T> Observable<T>.bindUntilEvent(owner: LifecycleOwner, event: Lifecycle.Event): Observable<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindUntilEvent(event))

fun <T> Flowable<T>.bindToLifecycle(owner: LifecycleOwner): Flowable<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindToLifecycle())

fun <T> Flowable<T>.bindUntilEvent(owner: LifecycleOwner, event: Lifecycle.Event): Flowable<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindUntilEvent(event))

fun <T> Single<T>.bindToLifecycle(owner: LifecycleOwner): Single<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindToLifecycle())

fun <T> Single<T>.bindUntilEvent(owner: LifecycleOwner, event: Lifecycle.Event): Single<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindUntilEvent(event))

fun <T> Maybe<T>.bindToLifecycle(owner: LifecycleOwner): Maybe<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindToLifecycle())

fun <T> Maybe<T>.bindUntilEvent(owner: LifecycleOwner, event: Lifecycle.Event): Maybe<T>
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindUntilEvent(event))

fun <T> Completable.bindToLifecycle(owner: LifecycleOwner): Completable
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindToLifecycle<Completable>())

fun <T> Completable.bindUntilEvent(owner: LifecycleOwner, event: Lifecycle.Event): Completable
= this.compose(AndroidLifecycle.createLifecycleProvider(owner).bindUntilEvent<Completable>(event))
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">rxlifecycle-android-lifecycle-kotlin</string>
</resources>
1 change: 1 addition & 0 deletions rxlifecycle-android-lifecycle/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
32 changes: 32 additions & 0 deletions rxlifecycle-android-lifecycle/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'

android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion

defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
}
}

repositories {
mavenCentral()
maven { url 'https://maven.google.com' }
}

dependencies {
compile project(':rxlifecycle')

compile rootProject.ext.rxAndroid
compile rootProject.ext.supportAnnotations
compile rootProject.ext.lifecycle
annotationProcessor rootProject.ext.lifecycleProcessor

testCompile rootProject.ext.junit
testCompile rootProject.ext.robolectric
}

apply from: "$rootDir/gradle/artifacts.gradle"
apply from: "$rootDir/gradle/gradle-mvn-push.gradle"

4 changes: 4 additions & 0 deletions rxlifecycle-android-lifecycle/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_NAME=RxLifecycle-Android-Lifecycle
POM_DESCRIPTION=RxLifecycle-Android-Lifecycle
POM_ARTIFACT_ID=rxlifecycle-android-lifecycle
POM_PACKAGING=aar
2 changes: 2 additions & 0 deletions rxlifecycle-android-lifecycle/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<manifest package="com.trello.rxlifecycle2.android.lifecycle" />

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.trello.lifecycle2.android.lifecycle;

import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.OnLifecycleEvent;
import android.support.annotation.CheckResult;

import com.trello.rxlifecycle2.LifecycleProvider;
import com.trello.rxlifecycle2.LifecycleTransformer;
import com.trello.rxlifecycle2.RxLifecycle;

import javax.annotation.Nonnull;

import io.reactivex.Observable;
import io.reactivex.subjects.BehaviorSubject;

/**
* Wraps a {@link LifecycleOwner} so that it can be used as a {@link LifecycleProvider}. For example,
* you can do
* <pre>{@code
* LifecycleProvider<Lifecycle.Event> provider = AndroidLifecycle.createLifecycleProvider(this);
* myObservable
* .compose(provider.bindLifecycle())
* .subscribe();
* }</pre>
* where {@code this} is a {@link android.arch.lifecycle.LifecycleActivity} or {@link android.arch.lifecycle.LifecycleFragment}.
*/
public final class AndroidLifecycle implements LifecycleProvider<Lifecycle.Event>, LifecycleObserver {

public static LifecycleProvider<Lifecycle.Event> createLifecycleProvider(LifecycleOwner owner) {
return new AndroidLifecycle(owner);
}

private final BehaviorSubject<Lifecycle.Event> lifecycleSubject = BehaviorSubject.create();

private AndroidLifecycle(LifecycleOwner owner) {
owner.getLifecycle().addObserver(this);
}

@Nonnull
@Override
@CheckResult
public Observable<Lifecycle.Event> lifecycle() {
return lifecycleSubject.hide();
}

@Nonnull
@Override
@CheckResult
public <T> LifecycleTransformer<T> bindUntilEvent(@Nonnull Lifecycle.Event event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}

@Nonnull
@Override
@CheckResult
public <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroidLifecycle.bindLifecycle(lifecycleSubject);
}

@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
void onEvent(LifecycleOwner owner, Lifecycle.Event event) {
lifecycleSubject.onNext(event);
if (event == Lifecycle.Event.ON_DESTROY) {
owner.getLifecycle().removeObserver(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.trello.lifecycle2.android.lifecycle;

import android.arch.lifecycle.Lifecycle;
import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;

import com.trello.rxlifecycle2.LifecycleTransformer;
import com.trello.rxlifecycle2.OutsideLifecycleException;

import io.reactivex.Observable;
import io.reactivex.functions.Function;

import static com.trello.rxlifecycle2.RxLifecycle.bind;

public final class RxLifecycleAndroidLifecycle {

private RxLifecycleAndroidLifecycle() {
throw new AssertionError("No instances");
}

/**
* Binds the given source to an Android lifecycle.
* <p>
* This helper automatically determines (based on the lifecycle sequence itself) when the source
* should stop emitting items. In the case that the lifecycle sequence is in the
* creation phase (ON_CREATE, ON_START, etc) it will choose the equivalent destructive phase (ON_DESTROY,
* ON_STOP, etc). If used in the destructive phase, the notifications will cease at the next event;
* for example, if used in ON_PAUSE, it will unsubscribe in ON_STOP.
*
* @param lifecycle the lifecycle sequence of an Activity
* @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the Activity lifecycle
*/
@NonNull
@CheckResult
public static <T> LifecycleTransformer<T> bindLifecycle(@NonNull Observable<Lifecycle.Event> lifecycle) {
return bind(lifecycle, LIFECYCLE);
}

private static final Function<Lifecycle.Event, Lifecycle.Event> LIFECYCLE = new Function<Lifecycle.Event, Lifecycle.Event>() {
@Override
public Lifecycle.Event apply(Lifecycle.Event lastEvent) throws Exception {
switch (lastEvent) {
case ON_CREATE:
return Lifecycle.Event.ON_DESTROY;
case ON_START:
return Lifecycle.Event.ON_STOP;
case ON_RESUME:
return Lifecycle.Event.ON_PAUSE;
case ON_PAUSE:
return Lifecycle.Event.ON_STOP;
case ON_STOP:
return Lifecycle.Event.ON_DESTROY;
case ON_DESTROY:
throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it.");
default:
throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
}
}
};
}
Loading