├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── stepstone │ │ └── reactiveusecasessample │ │ ├── MainActivity.kt │ │ ├── data │ │ ├── executor │ │ │ └── JobExecutor.kt │ │ ├── repository │ │ │ ├── ContentRepositoryImpl.kt │ │ │ ├── LocalPreferencesRepositoryImpl.kt │ │ │ └── TrackingRepositoryImpl.kt │ │ └── service │ │ │ └── ExternalChangeListenerImpl.kt │ │ ├── domain │ │ ├── executor │ │ │ ├── PostExecutionThread.kt │ │ │ └── ThreadExecutor.kt │ │ ├── interactor │ │ │ ├── CheckSampleFeatureStatusUseCase.kt │ │ │ ├── DisableSampleFeatureUseCase.kt │ │ │ ├── EnableSampleFeatureUseCase.kt │ │ │ ├── LoadContentUseCase.kt │ │ │ ├── ReactToExternalChangesUseCase.kt │ │ │ ├── UploadContentUseCase.kt │ │ │ └── base │ │ │ │ ├── BaseReactiveUseCase.kt │ │ │ │ ├── CompletableUseCase.kt │ │ │ │ ├── ObservableUseCase.kt │ │ │ │ ├── SingleUseCase.kt │ │ │ │ └── SynchronousUseCase.kt │ │ ├── model │ │ │ └── Content.kt │ │ ├── repository │ │ │ ├── ContentRepository.kt │ │ │ ├── LocalPreferencesRepository.kt │ │ │ └── TrackingRepository.kt │ │ └── service │ │ │ └── ExternalChangeListener.kt │ │ ├── internal │ │ ├── activity │ │ │ └── BaseActivity.kt │ │ ├── di │ │ │ ├── component │ │ │ │ └── ApplicationComponent.kt │ │ │ └── module │ │ │ │ ├── ActivityContributorModule.kt │ │ │ │ └── ApplicationModule.kt │ │ └── rx │ │ │ ├── EmptyCompletableObserver.kt │ │ │ ├── EmptyObserver.kt │ │ │ └── EmptySingleObserver.kt │ │ └── presentation │ │ ├── AndroidApplication.kt │ │ ├── UIThread.kt │ │ ├── completable │ │ ├── CompletableUseCaseSampleContract.kt │ │ ├── di │ │ │ └── CompletableUseCaseSampleActivityModule.kt │ │ ├── presenter │ │ │ └── CompletableUseCaseSamplePresenter.kt │ │ └── view │ │ │ └── CompletableUseCaseSampleActivity.kt │ │ ├── observable │ │ ├── ObservableUseCaseSampleContract.kt │ │ ├── di │ │ │ └── ObservableUseCaseSampleActivityModule.kt │ │ ├── presenter │ │ │ └── ObservableUseCaseSamplePresenter.kt │ │ └── view │ │ │ └── ObservableUseCaseSampleActivity.kt │ │ ├── single │ │ ├── SingleUseCaseSampleContract.kt │ │ ├── di │ │ │ └── SingleUseCaseSampleActivityModule.kt │ │ ├── presenter │ │ │ └── SingleUseCaseSamplePresenter.kt │ │ └── view │ │ │ └── SingleUseCaseSampleActivity.kt │ │ └── synchronous │ │ ├── SynchronousUseCaseSampleContract.kt │ │ ├── di │ │ └── SynchronousUseCaseSampleActivityModule.kt │ │ ├── presenter │ │ └── SynchronousUseCaseSamplePresenter.kt │ │ └── view │ │ └── SynchronousUseCaseSampleActivity.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_completable_use_case_sample.xml │ ├── activity_main.xml │ ├── activity_observable_use_case_sample.xml │ ├── activity_single_use_case_sample.xml │ └── activity_synchronous_use_case_sample.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2018 StepStone Services Sp. z o.o. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ReactiveUseCasesSample 2 | 3 | A sample app which showcases different kinds of Use Case classes - `SingleUseCase`, `ObservableUseCase`, `CompletableUseCase` and `SynchronousUseCase`. 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-kapt' 4 | 5 | android { 6 | compileSdkVersion 27 7 | defaultConfig { 8 | applicationId "com.stepstone.reactiveusecasessample" 9 | minSdkVersion 19 10 | targetSdkVersion 27 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 25 | implementation 'com.android.support:appcompat-v7:27.1.1' 26 | implementation 'com.android.support.constraint:constraint-layout:1.1.0' 27 | 28 | implementation 'com.jakewharton:butterknife:8.7.0' 29 | kapt 'com.jakewharton:butterknife-compiler:8.7.0' 30 | 31 | implementation 'com.google.dagger:dagger:2.13' 32 | implementation 'com.google.dagger:dagger-android-support:2.13' 33 | kapt 'com.google.dagger:dagger-compiler:2.13' 34 | kapt 'com.google.dagger:dagger-android-processor:2.13' 35 | 36 | implementation 'io.reactivex.rxjava2:rxjava:2.1.13' 37 | implementation("io.reactivex.rxjava2:rxandroid:2.0.2") 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample 19 | 20 | import android.content.Intent 21 | import android.os.Bundle 22 | import butterknife.OnClick 23 | import com.stepstone.reactiveusecasessample.internal.activity.BaseActivity 24 | import com.stepstone.reactiveusecasessample.presentation.completable.view.CompletableUseCaseSampleActivity 25 | import com.stepstone.reactiveusecasessample.presentation.observable.view.ObservableUseCaseSampleActivity 26 | import com.stepstone.reactiveusecasessample.presentation.single.view.SingleUseCaseSampleActivity 27 | import com.stepstone.reactiveusecasessample.presentation.synchronous.view.SynchronousUseCaseSampleActivity 28 | 29 | class MainActivity : BaseActivity() { 30 | 31 | override fun onCreate(savedInstanceState: Bundle?) { 32 | super.onCreate(savedInstanceState) 33 | setContentView(R.layout.activity_main) 34 | } 35 | 36 | @OnClick(R.id.singleUseCase) 37 | fun onSingleUseCase() { 38 | startActivity(Intent(this, SingleUseCaseSampleActivity::class.java)) 39 | } 40 | 41 | @OnClick(R.id.observableUseCase) 42 | fun onObservableUseCase() { 43 | startActivity(Intent(this, ObservableUseCaseSampleActivity::class.java)) 44 | } 45 | 46 | @OnClick(R.id.completableUseCase) 47 | fun onCompletableUseCase() { 48 | startActivity(Intent(this, CompletableUseCaseSampleActivity::class.java)) 49 | } 50 | 51 | @OnClick(R.id.synchronousUseCase) 52 | fun onSynchronousUseCase() { 53 | startActivity(Intent(this, SynchronousUseCaseSampleActivity::class.java)) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/data/executor/JobExecutor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Fernando Cejas Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Copied from https://github.com/android10/Android-CleanArchitecture and converted to Kotlin. 19 | */ 20 | 21 | package com.stepstone.reactiveusecasessample.data.executor 22 | 23 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 24 | import java.util.concurrent.Executor 25 | import java.util.concurrent.Executors 26 | import javax.inject.Inject 27 | import javax.inject.Singleton 28 | 29 | @Singleton 30 | class JobExecutor 31 | @Inject 32 | constructor() : ThreadExecutor { 33 | 34 | companion object { 35 | private const val THREAD_POOL = 3 36 | } 37 | 38 | private val threadPoolExecutor: Executor = Executors.newFixedThreadPool(THREAD_POOL) 39 | 40 | override fun execute(runnable: Runnable) { 41 | threadPoolExecutor.execute(runnable) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/data/repository/ContentRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.data.repository 19 | 20 | import com.stepstone.reactiveusecasessample.domain.model.Content 21 | import com.stepstone.reactiveusecasessample.domain.repository.ContentRepository 22 | import io.reactivex.Completable 23 | import io.reactivex.Single 24 | import java.util.concurrent.TimeUnit 25 | import javax.inject.Inject 26 | import javax.inject.Singleton 27 | 28 | @Singleton 29 | class ContentRepositoryImpl 30 | @Inject 31 | constructor() : ContentRepository { 32 | 33 | override fun loadContent(): Single { 34 | // an actual API call would take place here e.g. using Retrofit + some mapping from data layer to domain layer 35 | return Single.fromCallable { 36 | Content( 37 | "some title", 38 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." 39 | ) 40 | }.delay(1, TimeUnit.SECONDS) 41 | } 42 | 43 | override fun uploadContent(): Completable { 44 | // an actual API call would take place here e.g. using Retrofit 45 | return Completable.complete().delay(2L, TimeUnit.SECONDS) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/data/repository/LocalPreferencesRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.data.repository 19 | 20 | import android.app.Application 21 | import android.content.SharedPreferences 22 | import android.preference.PreferenceManager 23 | import com.stepstone.reactiveusecasessample.domain.repository.LocalPreferencesRepository 24 | import javax.inject.Inject 25 | import javax.inject.Singleton 26 | 27 | @Singleton 28 | class LocalPreferencesRepositoryImpl 29 | @Inject 30 | constructor(private val application: Application) : LocalPreferencesRepository { 31 | 32 | companion object { 33 | private const val SAMPLE_FEATURE_KEY = "sampleFeature" 34 | } 35 | 36 | private val sharedPreferences: SharedPreferences by lazy { 37 | PreferenceManager.getDefaultSharedPreferences( 38 | application 39 | ) 40 | } 41 | 42 | override fun enableSampleFeature() { 43 | sharedPreferences.edit() 44 | .putBoolean(SAMPLE_FEATURE_KEY, true) 45 | .apply() 46 | } 47 | 48 | override fun disableSampleFeature() { 49 | sharedPreferences.edit() 50 | .putBoolean(SAMPLE_FEATURE_KEY, false) 51 | .apply() 52 | } 53 | 54 | override fun isSampleFeatureEnabled(): Boolean = 55 | sharedPreferences.getBoolean(SAMPLE_FEATURE_KEY, false) 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/data/repository/TrackingRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.data.repository 19 | 20 | import android.util.Log 21 | import com.stepstone.reactiveusecasessample.domain.repository.TrackingRepository 22 | import javax.inject.Inject 23 | import javax.inject.Singleton 24 | 25 | @Singleton 26 | class TrackingRepositoryImpl 27 | @Inject 28 | constructor() : TrackingRepository { 29 | 30 | override fun trackSampleFeatureEnabled() { 31 | // Invoke an actual tracking library here instead 32 | Log.i("Tracking", "Sending a track action for custom feature enabled") 33 | } 34 | 35 | override fun trackSampleFeatureDisabled() { 36 | // Invoke an actual tracking library here instead 37 | Log.i("Tracking", "Sending a track action for custom feature disabled") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/data/service/ExternalChangeListenerImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.data.service 19 | 20 | import android.app.Application 21 | import android.content.BroadcastReceiver 22 | import android.content.Context 23 | import android.content.Intent 24 | import android.content.IntentFilter 25 | import android.support.v4.content.LocalBroadcastManager 26 | import com.stepstone.reactiveusecasessample.domain.service.ExternalChangeListener 27 | import io.reactivex.Observable 28 | import io.reactivex.subjects.PublishSubject 29 | import javax.inject.Inject 30 | 31 | class ExternalChangeListenerImpl 32 | @Inject 33 | constructor(application: Application) : ExternalChangeListener { 34 | 35 | private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(application) } 36 | 37 | private val externalChangeSubject = PublishSubject.create() 38 | 39 | private var externalChangeBroadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() { 40 | override fun onReceive(context: Context, intent: Intent) { 41 | val listingIdToUpdate = intent.extras?.getString("name") 42 | externalChangeSubject.onNext(ExternalChangeListener.Change( 43 | name = listingIdToUpdate ?: "unknown")) 44 | } 45 | } 46 | 47 | override fun onFavouriteChangeEvent(): Observable { 48 | val intentFilter = IntentFilter().apply { 49 | addAction("user_action") 50 | } 51 | localBroadcastManager.registerReceiver(externalChangeBroadcastReceiver, intentFilter) 52 | return externalChangeSubject 53 | } 54 | 55 | override fun dispose() { 56 | localBroadcastManager.unregisterReceiver(externalChangeBroadcastReceiver) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/executor/PostExecutionThread.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Fernando Cejas Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Copied from https://github.com/android10/Android-CleanArchitecture and converted to Kotlin. 19 | */ 20 | 21 | package com.stepstone.reactiveusecasessample.domain.executor 22 | 23 | import io.reactivex.Scheduler 24 | 25 | /** 26 | * Thread abstraction created to change the execution context from any thread to any other thread. 27 | * Useful to encapsulate a UI Thread for example, since some job will be done in background, an 28 | * implementation of this interface will change context and update the UI. 29 | */ 30 | interface PostExecutionThread { 31 | val scheduler: Scheduler 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/executor/ThreadExecutor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Fernando Cejas Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Copied from https://github.com/android10/Android-CleanArchitecture and converted to Kotlin. 19 | */ 20 | 21 | package com.stepstone.reactiveusecasessample.domain.executor 22 | 23 | import java.util.concurrent.Executor 24 | 25 | /** 26 | * Executor implementation can be based on different frameworks or techniques of asynchronous 27 | * execution, but every implementation will execute the 28 | * [com.stepstone.reactiveusecasessample.domain.interactor.BaseReactiveUseCase] out of the UI thread. 29 | */ 30 | interface ThreadExecutor : Executor 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/CheckSampleFeatureStatusUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor 19 | 20 | import com.stepstone.reactiveusecasessample.domain.interactor.base.SynchronousUseCase 21 | import com.stepstone.reactiveusecasessample.domain.repository.LocalPreferencesRepository 22 | import javax.inject.Inject 23 | 24 | class CheckSampleFeatureStatusUseCase 25 | @Inject 26 | constructor( 27 | private val localPreferencesRepository: LocalPreferencesRepository 28 | ) : SynchronousUseCase { 29 | 30 | override fun execute(params: Unit?): Boolean = 31 | localPreferencesRepository.isSampleFeatureEnabled() 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/DisableSampleFeatureUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor 19 | 20 | import com.stepstone.reactiveusecasessample.domain.interactor.base.SynchronousUseCase 21 | import com.stepstone.reactiveusecasessample.domain.repository.LocalPreferencesRepository 22 | import com.stepstone.reactiveusecasessample.domain.repository.TrackingRepository 23 | import javax.inject.Inject 24 | 25 | class DisableSampleFeatureUseCase 26 | @Inject 27 | constructor( 28 | private val trackingRepository: TrackingRepository, 29 | private val localPreferencesRepository: LocalPreferencesRepository 30 | ) : SynchronousUseCase { 31 | 32 | override fun execute(params: Unit?) { 33 | localPreferencesRepository.disableSampleFeature() 34 | trackingRepository.trackSampleFeatureDisabled() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/EnableSampleFeatureUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor 19 | 20 | import com.stepstone.reactiveusecasessample.domain.interactor.base.SynchronousUseCase 21 | import com.stepstone.reactiveusecasessample.domain.repository.LocalPreferencesRepository 22 | import com.stepstone.reactiveusecasessample.domain.repository.TrackingRepository 23 | import javax.inject.Inject 24 | 25 | class EnableSampleFeatureUseCase 26 | @Inject 27 | constructor( 28 | private val trackingRepository: TrackingRepository, 29 | private val localPreferencesRepository: LocalPreferencesRepository 30 | ) : SynchronousUseCase { 31 | 32 | override fun execute(params: Unit?) { 33 | localPreferencesRepository.enableSampleFeature() 34 | trackingRepository.trackSampleFeatureEnabled() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/LoadContentUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor 19 | 20 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 21 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 22 | import com.stepstone.reactiveusecasessample.domain.interactor.base.SingleUseCase 23 | import com.stepstone.reactiveusecasessample.domain.model.Content 24 | import com.stepstone.reactiveusecasessample.domain.repository.ContentRepository 25 | import io.reactivex.Single 26 | import javax.inject.Inject 27 | 28 | class LoadContentUseCase 29 | @Inject 30 | constructor( 31 | threadExecutor: ThreadExecutor, 32 | postExecutionThread: PostExecutionThread, 33 | private val contentRepository: ContentRepository 34 | ) : SingleUseCase(threadExecutor, postExecutionThread) { 35 | 36 | override fun buildUseCaseSingle(params: Unit?): Single { 37 | return contentRepository.loadContent() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/ReactToExternalChangesUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor 19 | 20 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 21 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 22 | import com.stepstone.reactiveusecasessample.domain.interactor.base.ObservableUseCase 23 | import com.stepstone.reactiveusecasessample.domain.service.ExternalChangeListener 24 | import io.reactivex.Observable 25 | import javax.inject.Inject 26 | 27 | class ReactToExternalChangesUseCase 28 | @Inject 29 | constructor( 30 | threadExecutor: ThreadExecutor, 31 | postExecutionThread: PostExecutionThread, 32 | private val externalChangeListener: ExternalChangeListener 33 | ) : ObservableUseCase(threadExecutor, postExecutionThread) { 34 | 35 | override fun buildUseCaseObservable(params: Unit?): Observable { 36 | return externalChangeListener.onFavouriteChangeEvent() 37 | .map { it.name } 38 | } 39 | 40 | override fun dispose() { 41 | super.dispose() 42 | externalChangeListener.dispose() 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/UploadContentUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor 19 | 20 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 21 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 22 | import com.stepstone.reactiveusecasessample.domain.interactor.base.CompletableUseCase 23 | import com.stepstone.reactiveusecasessample.domain.repository.ContentRepository 24 | import io.reactivex.Completable 25 | import javax.inject.Inject 26 | 27 | class UploadContentUseCase 28 | @Inject 29 | constructor( 30 | threadExecutor: ThreadExecutor, 31 | postExecutionThread: PostExecutionThread, 32 | private val contentRepository: ContentRepository 33 | ) : CompletableUseCase(threadExecutor, postExecutionThread) { 34 | 35 | override fun buildUseCaseCompletable(params: Unit?): Completable { 36 | return contentRepository.uploadContent() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/base/BaseReactiveUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor.base 19 | 20 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 21 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 22 | import io.reactivex.Scheduler 23 | import io.reactivex.disposables.CompositeDisposable 24 | import io.reactivex.disposables.Disposable 25 | import io.reactivex.schedulers.Schedulers 26 | 27 | abstract class BaseReactiveUseCase( 28 | threadExecutor: ThreadExecutor, 29 | postExecutionThread: PostExecutionThread 30 | ) { 31 | 32 | protected val threadExecutorScheduler: Scheduler = Schedulers.from(threadExecutor) 33 | 34 | protected val postExecutionThreadScheduler: Scheduler = postExecutionThread.scheduler 35 | 36 | private val disposables = CompositeDisposable() 37 | 38 | open fun dispose() { 39 | if (!disposables.isDisposed) { 40 | disposables.dispose() 41 | } 42 | } 43 | 44 | protected fun addDisposable(disposable: Disposable) { 45 | disposables.add(checkNotNull(disposable, { "disposable cannot be null!" })) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/base/CompletableUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor.base 19 | 20 | import com.stepstone.reactiveusecasessample.internal.rx.EmptyCompletableObserver 21 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 22 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 23 | import io.reactivex.Completable 24 | import io.reactivex.observers.DisposableCompletableObserver 25 | 26 | /** 27 | * Abstract class for a Use Case (Interactor in terms of Clean Architecture). 28 | * This interface represents a execution unit for different use cases (this means any use case 29 | * in the application should implement this contract). 30 | * 31 | * By convention each UseCase implementation will return the result using a [DisposableCompletableObserver] 32 | * that will execute its job in a background thread and will post the result in the UI thread. 33 | * 34 | * This use case is to be used when we expect no value to be emitted but rather for an action to be completed. 35 | * 36 | * @see Completable 37 | */ 38 | abstract class CompletableUseCase( 39 | threadExecutor: ThreadExecutor, 40 | postExecutionThread: PostExecutionThread 41 | ) : BaseReactiveUseCase(threadExecutor, postExecutionThread) { 42 | 43 | /** 44 | * Builds a [Completable] which will be used when executing the current [CompletableUseCase]. 45 | */ 46 | abstract fun buildUseCaseCompletable(params: Params? = null): Completable 47 | 48 | /** 49 | * Executes the current use case. 50 | * 51 | * @param observer [DisposableCompletableObserver] which will be listening to the observer build 52 | * by [buildUseCaseCompletable] method. 53 | * @param params Parameters (Optional) used to build/execute this use case. 54 | */ 55 | fun execute(observer: DisposableCompletableObserver = EmptyCompletableObserver(), params: Params? = null) { 56 | val completable = buildUseCaseCompletableWithSchedulers(params) 57 | addDisposable(completable.subscribeWith(observer)) 58 | } 59 | 60 | /** 61 | * Builds a [Completable] which will be used when executing the current [CompletableUseCase]. 62 | * With provided Schedulers 63 | */ 64 | private fun buildUseCaseCompletableWithSchedulers(params: Params?): Completable { 65 | return buildUseCaseCompletable(params) 66 | .subscribeOn(threadExecutorScheduler) 67 | .observeOn(postExecutionThreadScheduler) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/base/ObservableUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Fernando Cejas Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Copied from https://github.com/android10/Android-CleanArchitecture and converted to Kotlin. 19 | * Some stuff were extracted to BaseReactiveUseCase as well. 20 | */ 21 | 22 | package com.stepstone.reactiveusecasessample.domain.interactor.base 23 | 24 | import com.stepstone.reactiveusecasessample.internal.rx.EmptyObserver 25 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 26 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 27 | import io.reactivex.Observable 28 | import io.reactivex.observers.DisposableObserver 29 | 30 | /** 31 | * Abstract class for a Use Case (Interactor in terms of Clean Architecture). 32 | * This interface represents a execution unit for different use cases (this means any use case 33 | * in the application should implement this contract). 34 | * 35 | * By convention each UseCase implementation will return the result using a [DisposableObserver] 36 | * that will execute its job in a background thread and will post the result in the UI thread. 37 | * 38 | * This use case is to be used when we expect multiple values to be emitted via an [Observable]. 39 | * 40 | * 41 | */ 42 | abstract class ObservableUseCase( 43 | threadExecutor: ThreadExecutor, 44 | postExecutionThread: PostExecutionThread 45 | ) : BaseReactiveUseCase(threadExecutor, postExecutionThread) { 46 | 47 | /** 48 | * Builds an [Observable] which will be used when executing the current [ObservableUseCase]. 49 | */ 50 | abstract fun buildUseCaseObservable(params: Params? = null): Observable 51 | 52 | /** 53 | * Executes the current use case. 54 | * 55 | * @param observer [DisposableObserver] which will be listening to the observer build 56 | * by [buildUseCaseObservable] method. 57 | * @param params Parameters (Optional) used to build/execute this use case. 58 | */ 59 | fun execute(observer: DisposableObserver = EmptyObserver(), params: Params? = null) { 60 | val observable = buildUseCaseObservableWithSchedulers(params) 61 | addDisposable(observable.subscribeWith(observer)) 62 | } 63 | 64 | /** 65 | * Builds an [Observable] which will be used when executing the current [ObservableUseCase]. 66 | * With provided Schedulers 67 | */ 68 | private fun buildUseCaseObservableWithSchedulers(params: Params?): Observable { 69 | return buildUseCaseObservable(params) 70 | .subscribeOn(threadExecutorScheduler) 71 | .observeOn(postExecutionThreadScheduler) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/base/SingleUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor.base 19 | 20 | import com.stepstone.reactiveusecasessample.internal.rx.EmptySingleObserver 21 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 22 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 23 | import io.reactivex.Single 24 | import io.reactivex.observers.DisposableSingleObserver 25 | 26 | /** 27 | * Abstract class for a Use Case (Interactor in terms of Clean Architecture). 28 | * This interface represents a execution unit for different use cases (this means any use case 29 | * in the application should implement this contract). 30 | * 31 | * By convention each UseCase implementation will return the result using a [DisposableSingleObserver] 32 | * that will execute its job in a background thread and will post the result in the UI thread. 33 | * 34 | * This use case is to be used when we expect a single value to be emitted via a [Single]. 35 | */ 36 | abstract class SingleUseCase( 37 | threadExecutor: ThreadExecutor, 38 | postExecutionThread: PostExecutionThread 39 | ) : BaseReactiveUseCase(threadExecutor, postExecutionThread) { 40 | 41 | /** 42 | * Builds an [Single] which will be used when executing the current [SingleUseCase]. 43 | */ 44 | abstract fun buildUseCaseSingle(params: Params? = null): Single 45 | 46 | /** 47 | * Executes the current use case. 48 | * 49 | * @param observer [DisposableSingleObserver] which will be listening to the observer build 50 | * by [buildUseCaseSingle] method. 51 | * @param params Parameters (Optional) used to build/execute this use case. 52 | */ 53 | fun execute(observer: DisposableSingleObserver = EmptySingleObserver(), params: Params? = null) { 54 | val single = buildUseCaseSingleWithSchedulers(params) 55 | addDisposable(single.subscribeWith(observer)) 56 | } 57 | 58 | /** 59 | * Builds a [Single] which will be used when executing the current [SingleUseCase]. 60 | * With provided Schedulers 61 | */ 62 | private fun buildUseCaseSingleWithSchedulers(params: Params?): Single { 63 | return buildUseCaseSingle(params) 64 | .subscribeOn(threadExecutorScheduler) 65 | .observeOn(postExecutionThreadScheduler) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/interactor/base/SynchronousUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.interactor.base 19 | 20 | /** 21 | * Interface for a Use Case (Interactor in terms of Clean Architecture). 22 | * This interface represents a execution unit for different use cases (this means any use case 23 | * in the application should implement this contract). 24 | * 25 | * This use case is to be used for quick synchronous operations that do not require RxJava/threading. 26 | * They don't also need to be disposed. 27 | */ 28 | interface SynchronousUseCase { 29 | 30 | /** 31 | * Executes the current use case and returns the result immediately. 32 | * If this should not return anything then use [Unit] as [Results]. 33 | */ 34 | fun execute(params: Params? = null): Results 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/model/Content.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.model 19 | 20 | data class Content( 21 | val title: String, 22 | val description: String 23 | ) 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/repository/ContentRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.repository 19 | 20 | import com.stepstone.reactiveusecasessample.domain.model.Content 21 | import io.reactivex.Completable 22 | import io.reactivex.Single 23 | 24 | interface ContentRepository { 25 | 26 | fun loadContent(): Single 27 | 28 | fun uploadContent(): Completable 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/repository/LocalPreferencesRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.repository 19 | 20 | interface LocalPreferencesRepository { 21 | 22 | fun enableSampleFeature() 23 | 24 | fun disableSampleFeature() 25 | 26 | fun isSampleFeatureEnabled(): Boolean 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/repository/TrackingRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.repository 19 | 20 | interface TrackingRepository { 21 | 22 | fun trackSampleFeatureEnabled() 23 | 24 | fun trackSampleFeatureDisabled() 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/domain/service/ExternalChangeListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.domain.service 19 | 20 | import io.reactivex.Observable 21 | 22 | interface ExternalChangeListener { 23 | 24 | /** 25 | * Emits events when make some external changes 26 | */ 27 | fun onFavouriteChangeEvent(): Observable 28 | 29 | /** 30 | * Clears the listener. 31 | */ 32 | fun dispose() 33 | 34 | class Change(val name: String) 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/internal/activity/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.internal.activity 19 | 20 | import butterknife.ButterKnife 21 | import dagger.android.support.DaggerAppCompatActivity 22 | 23 | abstract class BaseActivity : DaggerAppCompatActivity() { 24 | 25 | override fun setContentView(layoutResID: Int) { 26 | super.setContentView(layoutResID) 27 | ButterKnife.bind(this) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/internal/di/component/ApplicationComponent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.internal.di.component 19 | 20 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 21 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 22 | import com.stepstone.reactiveusecasessample.internal.di.module.ActivityContributorModule 23 | import com.stepstone.reactiveusecasessample.internal.di.module.ApplicationModule 24 | import com.stepstone.reactiveusecasessample.presentation.AndroidApplication 25 | import dagger.Component 26 | import dagger.android.AndroidInjector 27 | import dagger.android.support.AndroidSupportInjectionModule 28 | import javax.inject.Singleton 29 | 30 | @Singleton 31 | @Component(modules = [AndroidSupportInjectionModule::class, ActivityContributorModule::class, ApplicationModule::class]) 32 | interface ApplicationComponent : AndroidInjector { 33 | 34 | fun threadExecutor(): ThreadExecutor 35 | 36 | fun postExecutionThread(): PostExecutionThread 37 | 38 | @Component.Builder 39 | abstract class Builder : AndroidInjector.Builder() { 40 | 41 | abstract override fun build(): ApplicationComponent 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/internal/di/module/ActivityContributorModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.internal.di.module 19 | 20 | import com.stepstone.reactiveusecasessample.MainActivity 21 | import com.stepstone.reactiveusecasessample.presentation.completable.di.CompletableUseCaseSampleActivityModule 22 | import com.stepstone.reactiveusecasessample.presentation.completable.view.CompletableUseCaseSampleActivity 23 | import com.stepstone.reactiveusecasessample.presentation.observable.di.ObservableUseCaseSampleActivityModule 24 | import com.stepstone.reactiveusecasessample.presentation.observable.view.ObservableUseCaseSampleActivity 25 | import com.stepstone.reactiveusecasessample.presentation.single.di.SingleUseCaseSampleActivityModule 26 | import com.stepstone.reactiveusecasessample.presentation.single.view.SingleUseCaseSampleActivity 27 | import com.stepstone.reactiveusecasessample.presentation.synchronous.di.SynchronousUseCaseSampleActivityModule 28 | import com.stepstone.reactiveusecasessample.presentation.synchronous.view.SynchronousUseCaseSampleActivity 29 | import dagger.Module 30 | import dagger.android.ContributesAndroidInjector 31 | 32 | @Module 33 | abstract class ActivityContributorModule { 34 | 35 | @ContributesAndroidInjector 36 | abstract fun contributeMainActivity(): MainActivity 37 | 38 | @ContributesAndroidInjector(modules = [SingleUseCaseSampleActivityModule::class]) 39 | abstract fun contributeSingleUseCaseActivity(): SingleUseCaseSampleActivity 40 | 41 | @ContributesAndroidInjector(modules = [ObservableUseCaseSampleActivityModule::class]) 42 | abstract fun contributeObservableUseCaseActivity(): ObservableUseCaseSampleActivity 43 | 44 | @ContributesAndroidInjector(modules = [CompletableUseCaseSampleActivityModule::class]) 45 | abstract fun contributeCompletableUseCaseActivity(): CompletableUseCaseSampleActivity 46 | 47 | @ContributesAndroidInjector(modules = [SynchronousUseCaseSampleActivityModule::class]) 48 | abstract fun contributeSynchronousUseCaseActivity(): SynchronousUseCaseSampleActivity 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/internal/di/module/ApplicationModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.internal.di.module 19 | 20 | import android.app.Application 21 | import com.stepstone.reactiveusecasessample.data.executor.JobExecutor 22 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 23 | import com.stepstone.reactiveusecasessample.domain.executor.ThreadExecutor 24 | import com.stepstone.reactiveusecasessample.presentation.AndroidApplication 25 | import com.stepstone.reactiveusecasessample.presentation.UIThread 26 | import dagger.Binds 27 | import dagger.Module 28 | 29 | @Module 30 | abstract class ApplicationModule { 31 | 32 | @Binds 33 | abstract fun bindThreadExecutor(jobExecutor: JobExecutor): ThreadExecutor 34 | 35 | @Binds 36 | abstract fun bindPostExecutionThread(uiThread: UIThread): PostExecutionThread 37 | 38 | @Binds 39 | abstract fun bindApplication(app: AndroidApplication): Application 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/internal/rx/EmptyCompletableObserver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.internal.rx 19 | 20 | import io.reactivex.observers.DisposableCompletableObserver 21 | 22 | open class EmptyCompletableObserver : DisposableCompletableObserver() { 23 | 24 | override fun onComplete() {} 25 | 26 | override fun onError(e: Throwable) {} 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/internal/rx/EmptyObserver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.internal.rx 19 | 20 | import io.reactivex.annotations.NonNull 21 | import io.reactivex.observers.DisposableObserver 22 | 23 | open class EmptyObserver : DisposableObserver() { 24 | 25 | override fun onNext(@NonNull t: T) {} 26 | 27 | override fun onError(@NonNull e: Throwable) {} 28 | 29 | override fun onComplete() {} 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/internal/rx/EmptySingleObserver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.internal.rx 19 | 20 | import io.reactivex.observers.DisposableSingleObserver 21 | 22 | open class EmptySingleObserver : DisposableSingleObserver() { 23 | 24 | override fun onSuccess(result: T) {} 25 | 26 | override fun onError(throwable: Throwable) {} 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/AndroidApplication.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation 19 | 20 | import com.stepstone.reactiveusecasessample.internal.di.component.DaggerApplicationComponent 21 | import dagger.android.AndroidInjector 22 | import dagger.android.support.DaggerApplication 23 | 24 | class AndroidApplication : DaggerApplication() { 25 | 26 | override fun applicationInjector(): AndroidInjector = 27 | DaggerApplicationComponent.builder().create(this) 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/UIThread.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Fernando Cejas Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Copied from https://github.com/android10/Android-CleanArchitecture and converted to Kotlin. 19 | */ 20 | 21 | package com.stepstone.reactiveusecasessample.presentation 22 | 23 | import com.stepstone.reactiveusecasessample.domain.executor.PostExecutionThread 24 | import io.reactivex.Scheduler 25 | import io.reactivex.android.schedulers.AndroidSchedulers 26 | import javax.inject.Inject 27 | import javax.inject.Singleton 28 | 29 | /** 30 | * This class provides main UI thread. 31 | */ 32 | @Singleton 33 | class UIThread 34 | @Inject 35 | constructor() : PostExecutionThread { 36 | 37 | override val scheduler: Scheduler 38 | get() = AndroidSchedulers.mainThread() 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/completable/CompletableUseCaseSampleContract.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.completable 19 | 20 | interface CompletableUseCaseSampleContract { 21 | 22 | interface View { 23 | 24 | fun showSuccess() 25 | 26 | fun showProgress() 27 | 28 | fun showError() 29 | } 30 | 31 | interface Presenter { 32 | 33 | fun attachView(mvpView: View) 34 | 35 | fun detachView() 36 | 37 | fun uploadData() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/completable/di/CompletableUseCaseSampleActivityModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.completable.di 19 | 20 | import com.stepstone.reactiveusecasessample.data.repository.ContentRepositoryImpl 21 | import com.stepstone.reactiveusecasessample.domain.repository.ContentRepository 22 | import com.stepstone.reactiveusecasessample.presentation.completable.CompletableUseCaseSampleContract 23 | import com.stepstone.reactiveusecasessample.presentation.completable.presenter.CompletableUseCaseSamplePresenter 24 | import dagger.Binds 25 | import dagger.Module 26 | 27 | @Module 28 | abstract class CompletableUseCaseSampleActivityModule { 29 | 30 | @Binds 31 | abstract fun bindPresenter(presenter: CompletableUseCaseSamplePresenter): CompletableUseCaseSampleContract.Presenter 32 | 33 | @Binds 34 | abstract fun bindContentRepository(repositoryImpl: ContentRepositoryImpl): ContentRepository 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/completable/presenter/CompletableUseCaseSamplePresenter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.completable.presenter 19 | 20 | import com.stepstone.reactiveusecasessample.domain.interactor.UploadContentUseCase 21 | import com.stepstone.reactiveusecasessample.presentation.completable.CompletableUseCaseSampleContract 22 | import io.reactivex.observers.DisposableCompletableObserver 23 | import javax.inject.Inject 24 | 25 | class CompletableUseCaseSamplePresenter 26 | @Inject 27 | constructor(private val uploadContentUseCase: UploadContentUseCase) : CompletableUseCaseSampleContract.Presenter { 28 | 29 | private var view: CompletableUseCaseSampleContract.View? = null 30 | 31 | override fun attachView(mvpView: CompletableUseCaseSampleContract.View) { 32 | view = mvpView 33 | } 34 | 35 | override fun detachView() { 36 | view = null 37 | uploadContentUseCase.dispose() 38 | } 39 | 40 | override fun uploadData() { 41 | view?.showProgress() 42 | uploadContentUseCase.execute(observer = UploadObserver()) 43 | } 44 | 45 | private inner class UploadObserver : DisposableCompletableObserver() { 46 | 47 | override fun onComplete() { 48 | view?.showSuccess() 49 | } 50 | 51 | override fun onError(e: Throwable) { 52 | view?.showError() 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/completable/view/CompletableUseCaseSampleActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.completable.view 19 | 20 | import android.os.Bundle 21 | import android.view.View 22 | import android.widget.ProgressBar 23 | import android.widget.TextView 24 | import butterknife.BindView 25 | import com.stepstone.reactiveusecasessample.internal.activity.BaseActivity 26 | import com.stepstone.reactiveusecasessample.presentation.completable.CompletableUseCaseSampleContract 27 | import com.stepstone.reactiveusecasessample.R 28 | import javax.inject.Inject 29 | 30 | class CompletableUseCaseSampleActivity : BaseActivity(), CompletableUseCaseSampleContract.View { 31 | 32 | @Inject 33 | internal lateinit var presenter: CompletableUseCaseSampleContract.Presenter 34 | 35 | @BindView(R.id.successMessage) 36 | internal lateinit var successMessage: TextView 37 | 38 | @BindView(R.id.progressBar) 39 | internal lateinit var progressBar: ProgressBar 40 | 41 | override fun onCreate(savedInstanceState: Bundle?) { 42 | super.onCreate(savedInstanceState) 43 | setContentView(R.layout.activity_completable_use_case_sample) 44 | presenter.apply { 45 | attachView(this@CompletableUseCaseSampleActivity) 46 | uploadData() 47 | } 48 | } 49 | 50 | override fun onDestroy() { 51 | presenter.detachView() 52 | super.onDestroy() 53 | } 54 | 55 | override fun showError() { 56 | } 57 | 58 | override fun showSuccess() { 59 | successMessage.visibility = View.VISIBLE 60 | progressBar.visibility = View.GONE 61 | } 62 | 63 | override fun showProgress() { 64 | progressBar.visibility = View.VISIBLE 65 | successMessage.visibility = View.GONE 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/observable/ObservableUseCaseSampleContract.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.observable 19 | 20 | interface ObservableUseCaseSampleContract { 21 | 22 | interface View { 23 | 24 | fun showExternalEvent(eventName: String) 25 | } 26 | 27 | interface Presenter { 28 | 29 | fun attachView(mvpView: View) 30 | 31 | fun detachView() 32 | 33 | fun loadExternalEvents() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/observable/di/ObservableUseCaseSampleActivityModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.observable.di 19 | 20 | import com.stepstone.reactiveusecasessample.data.service.ExternalChangeListenerImpl 21 | import com.stepstone.reactiveusecasessample.domain.service.ExternalChangeListener 22 | import com.stepstone.reactiveusecasessample.presentation.observable.ObservableUseCaseSampleContract 23 | import com.stepstone.reactiveusecasessample.presentation.observable.presenter.ObservableUseCaseSamplePresenter 24 | import dagger.Binds 25 | import dagger.Module 26 | 27 | @Module 28 | abstract class ObservableUseCaseSampleActivityModule { 29 | 30 | @Binds 31 | abstract fun bindPresenter(presenter: ObservableUseCaseSamplePresenter): ObservableUseCaseSampleContract.Presenter 32 | 33 | @Binds 34 | abstract fun bindExternalChangeListener(repositoryImpl: ExternalChangeListenerImpl): ExternalChangeListener 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/observable/presenter/ObservableUseCaseSamplePresenter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.observable.presenter 19 | 20 | import com.stepstone.reactiveusecasessample.domain.interactor.ReactToExternalChangesUseCase 21 | import com.stepstone.reactiveusecasessample.internal.rx.EmptyObserver 22 | import com.stepstone.reactiveusecasessample.presentation.observable.ObservableUseCaseSampleContract 23 | import javax.inject.Inject 24 | 25 | class ObservableUseCaseSamplePresenter 26 | @Inject 27 | constructor(private val reactToExternalChangesUseCase: ReactToExternalChangesUseCase) : ObservableUseCaseSampleContract.Presenter { 28 | 29 | private var view: ObservableUseCaseSampleContract.View? = null 30 | 31 | override fun attachView(mvpView: ObservableUseCaseSampleContract.View) { 32 | view = mvpView 33 | } 34 | 35 | override fun detachView() { 36 | view = null 37 | reactToExternalChangesUseCase.dispose() 38 | } 39 | 40 | override fun loadExternalEvents() { 41 | reactToExternalChangesUseCase.execute(observer = ExternalEventObserver()) 42 | } 43 | 44 | private inner class ExternalEventObserver : EmptyObserver() { 45 | 46 | override fun onNext(t: String) { 47 | view?.showExternalEvent(t) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/observable/view/ObservableUseCaseSampleActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.observable.view 19 | 20 | import android.app.Application 21 | import android.content.Intent 22 | import android.os.Bundle 23 | import android.support.v4.content.LocalBroadcastManager 24 | import android.widget.TextView 25 | import butterknife.BindView 26 | import butterknife.OnClick 27 | import com.stepstone.reactiveusecasessample.R 28 | import com.stepstone.reactiveusecasessample.internal.activity.BaseActivity 29 | import com.stepstone.reactiveusecasessample.presentation.observable.ObservableUseCaseSampleContract 30 | import javax.inject.Inject 31 | 32 | class ObservableUseCaseSampleActivity : BaseActivity(), ObservableUseCaseSampleContract.View { 33 | 34 | @Inject 35 | internal lateinit var presenter: ObservableUseCaseSampleContract.Presenter 36 | 37 | @BindView(R.id.title) 38 | internal lateinit var title: TextView 39 | 40 | @Inject 41 | internal lateinit var application: Application 42 | 43 | private var clickCount: Int = 0 44 | 45 | override fun onCreate(savedInstanceState: Bundle?) { 46 | super.onCreate(savedInstanceState) 47 | setContentView(R.layout.activity_observable_use_case_sample) 48 | presenter.apply { 49 | attachView(this@ObservableUseCaseSampleActivity) 50 | loadExternalEvents() 51 | } 52 | } 53 | 54 | override fun onDestroy() { 55 | presenter.detachView() 56 | super.onDestroy() 57 | } 58 | 59 | override fun showExternalEvent(eventName: String) { 60 | title.text = eventName 61 | } 62 | 63 | @OnClick(R.id.externalEventButton) 64 | fun onExternalEventButtonClicked() { 65 | /* The code below does not comply with Clean Architecture. 66 | * This event would normally get triggered somewhere else, 67 | * but for simplicity and demo purposes we use it here. 68 | */ 69 | clickCount++ 70 | val intent = Intent().apply { 71 | action = "user_action" 72 | putExtra("name", "User clicked button $clickCount times.") 73 | `package` = packageName 74 | } 75 | LocalBroadcastManager.getInstance(this).sendBroadcast(intent) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/single/SingleUseCaseSampleContract.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.single 19 | 20 | import com.stepstone.reactiveusecasessample.domain.model.Content 21 | 22 | interface SingleUseCaseSampleContract { 23 | 24 | interface View { 25 | 26 | fun showContent(content: Content) 27 | 28 | fun showProgress() 29 | 30 | fun showError() 31 | } 32 | 33 | interface Presenter { 34 | 35 | fun attachView(mvpView: View) 36 | 37 | fun detachView() 38 | 39 | fun loadContent() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/single/di/SingleUseCaseSampleActivityModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.single.di 19 | 20 | import com.stepstone.reactiveusecasessample.data.repository.ContentRepositoryImpl 21 | import com.stepstone.reactiveusecasessample.domain.repository.ContentRepository 22 | import com.stepstone.reactiveusecasessample.presentation.single.SingleUseCaseSampleContract 23 | import com.stepstone.reactiveusecasessample.presentation.single.presenter.SingleUseCaseSamplePresenter 24 | import dagger.Binds 25 | import dagger.Module 26 | 27 | @Module 28 | abstract class SingleUseCaseSampleActivityModule { 29 | 30 | @Binds 31 | abstract fun bindPresenter(presenter: SingleUseCaseSamplePresenter): SingleUseCaseSampleContract.Presenter 32 | 33 | @Binds 34 | abstract fun bindContentRepository(repositoryImpl: ContentRepositoryImpl): ContentRepository 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/single/presenter/SingleUseCaseSamplePresenter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.single.presenter 19 | 20 | import com.stepstone.reactiveusecasessample.domain.interactor.LoadContentUseCase 21 | import com.stepstone.reactiveusecasessample.domain.model.Content 22 | import com.stepstone.reactiveusecasessample.presentation.single.SingleUseCaseSampleContract 23 | import io.reactivex.observers.DisposableSingleObserver 24 | import javax.inject.Inject 25 | 26 | class SingleUseCaseSamplePresenter 27 | @Inject 28 | constructor(private val loadContentUseCase: LoadContentUseCase) : SingleUseCaseSampleContract.Presenter { 29 | 30 | private var view: SingleUseCaseSampleContract.View? = null 31 | 32 | override fun attachView(mvpView: SingleUseCaseSampleContract.View) { 33 | view = mvpView 34 | } 35 | 36 | override fun detachView() { 37 | view = null 38 | loadContentUseCase.dispose() 39 | } 40 | 41 | override fun loadContent() { 42 | view?.showProgress() 43 | loadContentUseCase.execute(observer = ContentObserver()) 44 | } 45 | 46 | private inner class ContentObserver : DisposableSingleObserver() { 47 | 48 | override fun onSuccess(t: Content) { 49 | view?.showContent(t) 50 | } 51 | 52 | override fun onError(e: Throwable) { 53 | view?.showError() 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/single/view/SingleUseCaseSampleActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.single.view 19 | 20 | import android.os.Bundle 21 | import android.view.View.GONE 22 | import android.view.View.VISIBLE 23 | import android.widget.ProgressBar 24 | import android.widget.TextView 25 | import butterknife.BindView 26 | import com.stepstone.reactiveusecasessample.R 27 | import com.stepstone.reactiveusecasessample.domain.model.Content 28 | import com.stepstone.reactiveusecasessample.internal.activity.BaseActivity 29 | import com.stepstone.reactiveusecasessample.presentation.single.SingleUseCaseSampleContract 30 | import javax.inject.Inject 31 | 32 | class SingleUseCaseSampleActivity : BaseActivity(), SingleUseCaseSampleContract.View { 33 | 34 | @Inject 35 | internal lateinit var presenter: SingleUseCaseSampleContract.Presenter 36 | 37 | @BindView(R.id.title) 38 | internal lateinit var title: TextView 39 | 40 | @BindView(R.id.description) 41 | internal lateinit var description: TextView 42 | 43 | @BindView(R.id.progressBar) 44 | internal lateinit var progressBar: ProgressBar 45 | 46 | override fun onCreate(savedInstanceState: Bundle?) { 47 | super.onCreate(savedInstanceState) 48 | setContentView(R.layout.activity_single_use_case_sample) 49 | presenter.apply { 50 | attachView(this@SingleUseCaseSampleActivity) 51 | loadContent() 52 | } 53 | } 54 | 55 | override fun onDestroy() { 56 | presenter.detachView() 57 | super.onDestroy() 58 | } 59 | 60 | override fun showContent(content: Content) { 61 | progressBar.visibility = GONE 62 | title.apply { 63 | visibility = VISIBLE 64 | text = content.title 65 | } 66 | description.apply { 67 | visibility = VISIBLE 68 | text = content.description 69 | } 70 | } 71 | 72 | override fun showProgress() { 73 | progressBar.visibility = VISIBLE 74 | title.visibility = GONE 75 | description.visibility = GONE 76 | } 77 | 78 | override fun showError() { 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/synchronous/SynchronousUseCaseSampleContract.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.synchronous 19 | 20 | interface SynchronousUseCaseSampleContract { 21 | 22 | interface View { 23 | 24 | fun setToggleStatus(enabled: Boolean) 25 | } 26 | 27 | interface Presenter { 28 | 29 | fun attachView(mvpView: View) 30 | 31 | fun detachView() 32 | 33 | fun toggleSampleFeature(enabled: Boolean) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/synchronous/di/SynchronousUseCaseSampleActivityModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.synchronous.di 19 | 20 | import com.stepstone.reactiveusecasessample.data.repository.LocalPreferencesRepositoryImpl 21 | import com.stepstone.reactiveusecasessample.data.repository.TrackingRepositoryImpl 22 | import com.stepstone.reactiveusecasessample.domain.repository.LocalPreferencesRepository 23 | import com.stepstone.reactiveusecasessample.domain.repository.TrackingRepository 24 | import com.stepstone.reactiveusecasessample.presentation.synchronous.SynchronousUseCaseSampleContract 25 | import com.stepstone.reactiveusecasessample.presentation.synchronous.presenter.SynchronousUseCaseSamplePresenter 26 | import dagger.Binds 27 | import dagger.Module 28 | 29 | @Module 30 | abstract class SynchronousUseCaseSampleActivityModule { 31 | 32 | @Binds 33 | abstract fun bindPresenter(presenter: SynchronousUseCaseSamplePresenter): SynchronousUseCaseSampleContract.Presenter 34 | 35 | @Binds 36 | abstract fun bindTrackingRepository(trackingRepositoryImpl: TrackingRepositoryImpl): TrackingRepository 37 | 38 | @Binds 39 | abstract fun bindLocalPreferencesRepository(localPreferencesRepositoryImpl: LocalPreferencesRepositoryImpl): LocalPreferencesRepository 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/synchronous/presenter/SynchronousUseCaseSamplePresenter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.synchronous.presenter 19 | 20 | import com.stepstone.reactiveusecasessample.domain.interactor.CheckSampleFeatureStatusUseCase 21 | import com.stepstone.reactiveusecasessample.domain.interactor.DisableSampleFeatureUseCase 22 | import com.stepstone.reactiveusecasessample.domain.interactor.EnableSampleFeatureUseCase 23 | import com.stepstone.reactiveusecasessample.presentation.synchronous.SynchronousUseCaseSampleContract 24 | import javax.inject.Inject 25 | 26 | class SynchronousUseCaseSamplePresenter 27 | @Inject 28 | constructor( 29 | private val enableSampleFeatureUseCase: EnableSampleFeatureUseCase, 30 | private val disableSampleFeatureUseCase: DisableSampleFeatureUseCase, 31 | private val checkSampleFeatureStatusUseCase: CheckSampleFeatureStatusUseCase 32 | ) : SynchronousUseCaseSampleContract.Presenter { 33 | 34 | private var view: SynchronousUseCaseSampleContract.View? = null 35 | 36 | override fun attachView(mvpView: SynchronousUseCaseSampleContract.View) { 37 | view = mvpView 38 | view?.setToggleStatus(checkSampleFeatureStatusUseCase.execute()) 39 | } 40 | 41 | override fun detachView() { 42 | view = null 43 | } 44 | 45 | override fun toggleSampleFeature(enabled: Boolean) { 46 | if (enabled) { 47 | enableSampleFeatureUseCase.execute() 48 | } else { 49 | disableSampleFeatureUseCase.execute() 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/stepstone/reactiveusecasessample/presentation/synchronous/view/SynchronousUseCaseSampleActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 StepStone Services Sp. z o.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.stepstone.reactiveusecasessample.presentation.synchronous.view 19 | 20 | import android.os.Bundle 21 | import android.support.v7.widget.SwitchCompat 22 | import butterknife.BindView 23 | import butterknife.OnCheckedChanged 24 | import com.stepstone.reactiveusecasessample.R 25 | import com.stepstone.reactiveusecasessample.internal.activity.BaseActivity 26 | import com.stepstone.reactiveusecasessample.presentation.synchronous.SynchronousUseCaseSampleContract 27 | import javax.inject.Inject 28 | 29 | class SynchronousUseCaseSampleActivity : BaseActivity(), SynchronousUseCaseSampleContract.View { 30 | 31 | @Inject 32 | internal lateinit var presenter: SynchronousUseCaseSampleContract.Presenter 33 | 34 | @BindView(R.id.toggle) 35 | internal lateinit var toggle: SwitchCompat 36 | 37 | override fun onCreate(savedInstanceState: Bundle?) { 38 | super.onCreate(savedInstanceState) 39 | setContentView(R.layout.activity_synchronous_use_case_sample) 40 | presenter.apply { 41 | attachView(this@SynchronousUseCaseSampleActivity) 42 | } 43 | } 44 | 45 | override fun onDestroy() { 46 | presenter.detachView() 47 | super.onDestroy() 48 | } 49 | 50 | override fun setToggleStatus(enabled: Boolean) { 51 | toggle.isChecked = enabled 52 | } 53 | 54 | @OnCheckedChanged(R.id.toggle) 55 | fun onToggleCheckedChanged(checked: Boolean) { 56 | presenter.toggleSampleFeature(checked) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_completable_use_case_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 22 | 23 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |