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

Sample app! #97

Merged
merged 19 commits into from
Oct 1, 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
59 changes: 59 additions & 0 deletions sample/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2017. Uber Technologies
*
* 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.
*/

buildscript {
repositories {
jcenter()
google()
}

dependencies {
classpath deps.build.gradlePlugins.android
classpath deps.build.gradlePlugins.kotlin
}
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
compileSdkVersion deps.build.compileSdkVersion
buildToolsVersion deps.build.buildToolsVersion

defaultConfig {
minSdkVersion deps.build.minSdkVersion
targetSdkVersion deps.build.targetSdkVersion
}
compileOptions {
// TODO Go to 1.8 + D8 on AGP 3.x
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}

dependencies {
provided deps.misc.javaxExtras
compile project(':autodispose')
compile project(':autodispose-android')
compile project(':autodispose-android-archcomponents')
compile project(':autodispose-kotlin')
compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.android.support.constraint:constraint-layout:1.1.0-beta1'
compile 'com.android.support:design:26.1.0'
}
55 changes: 55 additions & 0 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2017. Uber Technologies
~
~ 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.uber.autodispose.sample">

<application
android:allowBackup="true"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:fullBackupContent="@null"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">

<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".KotlinActivity"
android:label="@string/app_name_kotlin"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">

<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2017. Uber Technologies
*
* 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 android.support.v7.widget;

import android.view.View;

/**
* A bind-aware {@link RecyclerView.ViewHolder} implementation that knows when it's bound or
* unbound.
* <p>
* Disclaimer: This is in no way supported and THIS COULD BREAK AT ANY TIME. Left for research.
*/
public abstract class BindAwareViewHolder extends RecyclerView.ViewHolder {

public BindAwareViewHolder(View itemView) {
super(itemView);
}

protected void onBind() {

}

protected void onUnbind() {

}

@Override void setFlags(int flags, int mask) {
boolean wasBound = isBound();
super.setFlags(flags, mask);
notifyBinding(wasBound, isBound());
}

@Override void addFlags(int flags) {
boolean wasBound = isBound();
super.addFlags(flags);
notifyBinding(wasBound, isBound());
}

@Override void clearPayload() {
boolean wasBound = isBound();
super.clearPayload();
notifyBinding(wasBound, isBound());
}

@Override void resetInternal() {
boolean wasBound = isBound();
super.resetInternal();
notifyBinding(wasBound, isBound());
}

private void notifyBinding(boolean previousBound, boolean currentBound) {
if (previousBound && !currentBound) {
onUnbind();
} else if (!previousBound && currentBound) {
onBind();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2017. Uber Technologies
*
* 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.uber.autodispose.recipes;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import com.uber.autodispose.LifecycleEndedException;
import com.uber.autodispose.LifecycleScopeProvider;
import io.reactivex.Observable;
import io.reactivex.functions.Function;
import io.reactivex.subjects.BehaviorSubject;

/**
* An {@link Activity} example implementation for making one implement {@link
* LifecycleScopeProvider}. One would normally use this as a base activity class to extend others
* from.
*/
public abstract class AutoDisposeActivity extends Activity
implements LifecycleScopeProvider<AutoDisposeActivity.ActivityEvent> {

public enum ActivityEvent {
CREATE, START, RESUME, PAUSE, STOP, DESTROY
}

/**
* This is a function of current event -> target disposal event. That is to say that if event A
* returns B, then any stream subscribed to during A will autodispose on B. In Android, we make
* symmetric boundary conditions. Create -> Destroy, Start -> Stop, etc. For anything after Resume
* we dispose on the next immediate destruction event. Subscribing after Destroy is an error.
*/
private static Function<ActivityEvent, ActivityEvent> CORRESPONDING_EVENTS =
new Function<ActivityEvent, ActivityEvent>() {
@Override public ActivityEvent apply(ActivityEvent activityEvent) throws Exception {
switch (activityEvent) {
case CREATE:
return ActivityEvent.DESTROY;
case START:
return ActivityEvent.STOP;
case RESUME:
return ActivityEvent.PAUSE;
case PAUSE:
return ActivityEvent.STOP;
case STOP:
return ActivityEvent.DESTROY;
default:
throw new LifecycleEndedException("Cannot bind to Activity lifecycle after destroy.");
}
}
};

private final BehaviorSubject<ActivityEvent> lifecycleEvents = BehaviorSubject.create();

@Override public Observable<ActivityEvent> lifecycle() {
return lifecycleEvents.hide();
}

@Override public Function<ActivityEvent, ActivityEvent> correspondingEvents() {
return CORRESPONDING_EVENTS;
}

@Nullable @Override public ActivityEvent peekLifecycle() {
return lifecycleEvents.getValue();
}

@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleEvents.onNext(ActivityEvent.CREATE);
}

@Override protected void onStart() {
super.onStart();
lifecycleEvents.onNext(ActivityEvent.START);
}

@Override protected void onResume() {
super.onResume();
lifecycleEvents.onNext(ActivityEvent.RESUME);
}

@Override protected void onPause() {
lifecycleEvents.onNext(ActivityEvent.PAUSE);
super.onPause();
}

@Override protected void onStop() {
lifecycleEvents.onNext(ActivityEvent.STOP);
super.onStop();
}

@Override protected void onDestroy() {
lifecycleEvents.onNext(ActivityEvent.DESTROY);
super.onDestroy();
}
}
Loading