diff --git a/buildsystem/dependencies.gradle b/buildsystem/dependencies.gradle index 7ce44705..c14302db 100644 --- a/buildsystem/dependencies.gradle +++ b/buildsystem/dependencies.gradle @@ -1,82 +1,87 @@ allprojects { - repositories { - jcenter() - } + repositories { + jcenter() + } } ext { - //Android - androidBuildToolsVersion = "23.0.1" - androidMinSdkVersion = 15 - androidTargetSdkVersion = 21 - androidCompileSdkVersion = 21 + //Android + androidBuildToolsVersion = "23.0.1" + androidMinSdkVersion = 15 + androidTargetSdkVersion = 21 + androidCompileSdkVersion = 21 - //Libraries - daggerVersion = '2.0.2' - butterKnifeVersion = '7.0.1' - recyclerViewVersion = '21.0.3' - rxJavaVersion = '1.0.14' - rxAndroidVersion = '1.0.1' - javaxAnnotationVersion = '1.0' - gsonVersion = '2.3' - okHttpVersion = '2.5.0' - androidAnnotationsVersion = '21.0.3' + //Libraries + daggerVersion = '2.0.2' + butterKnifeVersion = '7.0.1' + recyclerViewVersion = '21.0.3' + rxJavaVersion = '1.0.14' + rxAndroidVersion = '1.0.1' + javaxAnnotationVersion = '1.0' + gsonVersion = '2.3' + okHttpVersion = '2.5.0' + androidAnnotationsVersion = '21.0.3' - //Testing - robolectricVersion = '3.0' - jUnitVersion = '4.12' - assertJVersion = '1.7.1' - mockitoVersion = '1.9.5' - dexmakerVersion = '1.0' - espressoVersion = '2.0' - testingSupportLibVersion = '0.1' + //Testing + robolectricVersion = '3.0' + jUnitVersion = '4.12' + assertJVersion = '1.7.1' + mockitoVersion = '1.9.5' + dexmakerVersion = '1.0' + espressoVersion = '2.0' + testingSupportLibVersion = '0.1' + //LeakCanary + leakCanaryVersion = '1.3.1' - presentationDependencies = [ - daggerCompiler: "com.google.dagger:dagger-compiler:${daggerVersion}", - dagger: "com.google.dagger:dagger:${daggerVersion}", - butterKnife: "com.jakewharton:butterknife:${butterKnifeVersion}", - recyclerView: "com.android.support:recyclerview-v7:${recyclerViewVersion}", - rxJava: "io.reactivex:rxjava:${rxJavaVersion}", - rxAndroid: "io.reactivex:rxandroid:${rxAndroidVersion}", - javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}", - ] - presentationTestDependencies = [ - mockito: "org.mockito:mockito-core:${mockitoVersion}", - dexmaker: "com.google.dexmaker:dexmaker:${dexmakerVersion}", - dexmakerMockito: "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}", - espresso: "com.android.support.test.espresso:espresso-core:${espressoVersion}", - testingSupportLib: "com.android.support.test:testing-support-lib:${testingSupportLibVersion}", - ] - domainDependencies = [ - daggerCompiler: "com.google.dagger:dagger-compiler:${daggerVersion}", - dagger: "com.google.dagger:dagger:${daggerVersion}", - javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}", - rxJava: "io.reactivex:rxjava:${rxJavaVersion}", - ] + presentationDependencies = [ + daggerCompiler : "com.google.dagger:dagger-compiler:${daggerVersion}", + dagger : "com.google.dagger:dagger:${daggerVersion}", + butterKnife : "com.jakewharton:butterknife:${butterKnifeVersion}", + recyclerView : "com.android.support:recyclerview-v7:${recyclerViewVersion}", + rxJava : "io.reactivex:rxjava:${rxJavaVersion}", + rxAndroid : "io.reactivex:rxandroid:${rxAndroidVersion}", + javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}", + leakCanary : "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}", + ] - domainTestDependencies = [ - junit: "junit:junit:${jUnitVersion}", - mockito: "org.mockito:mockito-core:${mockitoVersion}", - ] + presentationTestDependencies = [ + mockito : "org.mockito:mockito-core:${mockitoVersion}", + dexmaker : "com.google.dexmaker:dexmaker:${dexmakerVersion}", + dexmakerMockito : "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}", + espresso : "com.android.support.test.espresso:espresso-core:${espressoVersion}", + testingSupportLib: "com.android.support.test:testing-support-lib:${testingSupportLibVersion}", + ] - dataDependencies = [ - daggerCompiler: "com.google.dagger:dagger-compiler:${daggerVersion}", - dagger: "com.google.dagger:dagger:${daggerVersion}", - okHttp: "com.squareup.okhttp:okhttp:${okHttpVersion}", - gson: "com.google.code.gson:gson:${gsonVersion}", - rxJava: "io.reactivex:rxjava:${rxJavaVersion}", - rxAndroid: "io.reactivex:rxandroid:${rxAndroidVersion}", - javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}", - androidAnnotations: "com.android.support:support-annotations:${androidAnnotationsVersion}" - ] + domainDependencies = [ + daggerCompiler : "com.google.dagger:dagger-compiler:${daggerVersion}", + dagger : "com.google.dagger:dagger:${daggerVersion}", + javaxAnnotation: "javax.annotation:jsr250-api:${javaxAnnotationVersion}", + rxJava : "io.reactivex:rxjava:${rxJavaVersion}", + ] - dataTestDependencies = [ - junit: "junit:junit:${jUnitVersion}", - assertj: "org.assertj:assertj-core:${assertJVersion}", - mockito: "org.mockito:mockito-core:${mockitoVersion}", - robolectric: "org.robolectric:robolectric:${robolectricVersion}", - ] + domainTestDependencies = [ + junit : "junit:junit:${jUnitVersion}", + mockito: "org.mockito:mockito-core:${mockitoVersion}", + ] + + dataDependencies = [ + daggerCompiler : "com.google.dagger:dagger-compiler:${daggerVersion}", + dagger : "com.google.dagger:dagger:${daggerVersion}", + okHttp : "com.squareup.okhttp:okhttp:${okHttpVersion}", + gson : "com.google.code.gson:gson:${gsonVersion}", + rxJava : "io.reactivex:rxjava:${rxJavaVersion}", + rxAndroid : "io.reactivex:rxandroid:${rxAndroidVersion}", + javaxAnnotation : "javax.annotation:jsr250-api:${javaxAnnotationVersion}", + androidAnnotations: "com.android.support:support-annotations:${androidAnnotationsVersion}" + ] + + dataTestDependencies = [ + junit : "junit:junit:${jUnitVersion}", + assertj : "org.assertj:assertj-core:${assertJVersion}", + mockito : "org.mockito:mockito-core:${mockitoVersion}", + robolectric: "org.robolectric:robolectric:${robolectricVersion}", + ] } diff --git a/presentation/build.gradle b/presentation/build.gradle index 5c256f46..16e4defb 100644 --- a/presentation/build.gradle +++ b/presentation/build.gradle @@ -71,6 +71,7 @@ dependencies { compile presentationDependencies.recyclerView compile presentationDependencies.rxJava compile presentationDependencies.rxAndroid + compile presentationDependencies.leakCanary provided presentationDependencies.javaxAnnotation androidTestCompile presentationTestDependencies.mockito diff --git a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/AndroidApplication.java b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/AndroidApplication.java index d8cdb4eb..38a7ab62 100644 --- a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/AndroidApplication.java +++ b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/AndroidApplication.java @@ -5,7 +5,7 @@ * 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 + * 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, @@ -19,6 +19,7 @@ import com.fernandocejas.android10.sample.presentation.internal.di.components.ApplicationComponent; import com.fernandocejas.android10.sample.presentation.internal.di.components.DaggerApplicationComponent; import com.fernandocejas.android10.sample.presentation.internal.di.modules.ApplicationModule; +import com.squareup.leakcanary.LeakCanary; /** * Android Main Application @@ -30,12 +31,12 @@ public class AndroidApplication extends Application { @Override public void onCreate() { super.onCreate(); this.initializeInjector(); + LeakCanary.install(this); } private void initializeInjector() { - this.applicationComponent = DaggerApplicationComponent.builder() - .applicationModule(new ApplicationModule(this)) - .build(); + this.applicationComponent = + DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build(); } public ApplicationComponent getApplicationComponent() { diff --git a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/SubscriptionDecorator.java b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/SubscriptionDecorator.java new file mode 100644 index 00000000..e0118fe3 --- /dev/null +++ b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/SubscriptionDecorator.java @@ -0,0 +1,58 @@ +package com.fernandocejas.android10.sample.presentation; + +import android.support.annotation.NonNull; +import rx.Subscriber; +import rx.Subscription; + +/** + * Created by jorgis on 1/19/16. + */ +public class SubscriptionDecorator extends Subscriber { + private Subscriber subscriber; + + public SubscriptionDecorator(Subscriber subscriber) { + this.subscriber = subscriber; + this.add(new DisposingSubscription(this)); + } + + @Override public void onCompleted() { + if (subscriber != null) { + subscriber.onCompleted(); + } + } + + @Override public void onError(Throwable e) { + if (subscriber != null) { + subscriber.onError(e); + } + } + + @Override public void onNext(T o) { + if (subscriber != null) { + subscriber.onNext(o); + } + } + + public void disposeDependencies() { + subscriber = null; + } + + private static class DisposingSubscription implements Subscription { + + private final SubscriptionDecorator callback; + private boolean unsubscribed; + + private DisposingSubscription(@NonNull SubscriptionDecorator callback) { + this.callback = callback; + } + + @Override public void unsubscribe() { + callback.disposeDependencies(); + unsubscribed = true; + } + + @Override public boolean isUnsubscribed() { + return unsubscribed; + } + } +} diff --git a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserDetailsPresenter.java b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserDetailsPresenter.java index 6c09e4ab..dc0181cb 100644 --- a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserDetailsPresenter.java +++ b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserDetailsPresenter.java @@ -5,7 +5,7 @@ * 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 + * 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, @@ -21,6 +21,7 @@ import com.fernandocejas.android10.sample.domain.exception.ErrorBundle; import com.fernandocejas.android10.sample.domain.interactor.DefaultSubscriber; import com.fernandocejas.android10.sample.domain.interactor.UseCase; +import com.fernandocejas.android10.sample.presentation.SubscriptionDecorator; import com.fernandocejas.android10.sample.presentation.exception.ErrorMessageFactory; import com.fernandocejas.android10.sample.presentation.internal.di.PerActivity; import com.fernandocejas.android10.sample.presentation.mapper.UserModelDataMapper; @@ -34,8 +35,7 @@ * {@link Presenter} that controls communication between views and models of the presentation * layer. */ -@PerActivity -public class UserDetailsPresenter implements Presenter { +@PerActivity public class UserDetailsPresenter implements Presenter { /** id used to retrieve user details */ private int userId; @@ -45,8 +45,7 @@ public class UserDetailsPresenter implements Presenter { private final UseCase getUserDetailsUseCase; private final UserModelDataMapper userModelDataMapper; - @Inject - public UserDetailsPresenter(@Named("userDetails") UseCase getUserDetailsUseCase, + @Inject public UserDetailsPresenter(@Named("userDetails") UseCase getUserDetailsUseCase, UserModelDataMapper userModelDataMapper) { this.getUserDetailsUseCase = getUserDetailsUseCase; this.userModelDataMapper = userModelDataMapper; @@ -56,9 +55,11 @@ public void setView(@NonNull UserDetailsView view) { this.viewDetailsView = view; } - @Override public void resume() {} + @Override public void resume() { + } - @Override public void pause() {} + @Override public void pause() { + } @Override public void destroy() { this.getUserDetailsUseCase.unsubscribe(); @@ -98,8 +99,8 @@ private void hideViewRetry() { } private void showErrorMessage(ErrorBundle errorBundle) { - String errorMessage = ErrorMessageFactory.create(this.viewDetailsView.getContext(), - errorBundle.getException()); + String errorMessage = + ErrorMessageFactory.create(this.viewDetailsView.getContext(), errorBundle.getException()); this.viewDetailsView.showError(errorMessage); } @@ -109,11 +110,10 @@ private void showUserDetailsInView(User user) { } private void getUserDetails() { - this.getUserDetailsUseCase.execute(new UserDetailsSubscriber()); + this.getUserDetailsUseCase.execute(new SubscriptionDecorator<>(new UserDetailsSubscriber())); } - @RxLogSubscriber - private final class UserDetailsSubscriber extends DefaultSubscriber { + @RxLogSubscriber private final class UserDetailsSubscriber extends DefaultSubscriber { @Override public void onCompleted() { UserDetailsPresenter.this.hideViewLoading(); diff --git a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserListPresenter.java b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserListPresenter.java index 75ab5866..02410600 100644 --- a/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserListPresenter.java +++ b/presentation/src/main/java/com/fernandocejas/android10/sample/presentation/presenter/UserListPresenter.java @@ -5,7 +5,7 @@ * 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 + * 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, @@ -21,6 +21,7 @@ import com.fernandocejas.android10.sample.domain.exception.ErrorBundle; import com.fernandocejas.android10.sample.domain.interactor.DefaultSubscriber; import com.fernandocejas.android10.sample.domain.interactor.UseCase; +import com.fernandocejas.android10.sample.presentation.SubscriptionDecorator; import com.fernandocejas.android10.sample.presentation.exception.ErrorMessageFactory; import com.fernandocejas.android10.sample.presentation.internal.di.PerActivity; import com.fernandocejas.android10.sample.presentation.mapper.UserModelDataMapper; @@ -35,16 +36,15 @@ * {@link Presenter} that controls communication between views and models of the presentation * layer. */ -@PerActivity -public class UserListPresenter implements Presenter { +@PerActivity public class UserListPresenter implements Presenter { private UserListView viewListView; private final UseCase getUserListUseCase; private final UserModelDataMapper userModelDataMapper; - @Inject - public UserListPresenter(@Named("userList") UseCase getUserListUserCase, UserModelDataMapper userModelDataMapper) { + @Inject public UserListPresenter(@Named("userList") UseCase getUserListUserCase, + UserModelDataMapper userModelDataMapper) { this.getUserListUseCase = getUserListUserCase; this.userModelDataMapper = userModelDataMapper; } @@ -53,9 +53,11 @@ public void setView(@NonNull UserListView view) { this.viewListView = view; } - @Override public void resume() {} + @Override public void resume() { + } - @Override public void pause() {} + @Override public void pause() { + } @Override public void destroy() { this.getUserListUseCase.unsubscribe(); @@ -98,8 +100,8 @@ private void hideViewRetry() { } private void showErrorMessage(ErrorBundle errorBundle) { - String errorMessage = ErrorMessageFactory.create(this.viewListView.getContext(), - errorBundle.getException()); + String errorMessage = + ErrorMessageFactory.create(this.viewListView.getContext(), errorBundle.getException()); this.viewListView.showError(errorMessage); } @@ -110,7 +112,7 @@ private void showUsersCollectionInView(Collection usersCollection) { } private void getUserList() { - this.getUserListUseCase.execute(new UserListSubscriber()); + this.getUserListUseCase.execute(new SubscriptionDecorator<>(new UserListSubscriber())); } private final class UserListSubscriber extends DefaultSubscriber> {