├── app ├── .gitignore ├── src │ ├── test │ │ ├── resources │ │ │ └── mockito-extensions │ │ │ │ └── org.mockito.plugins.MockMaker │ │ └── java │ │ │ └── me │ │ │ └── jorgecastillo │ │ │ └── kodein │ │ │ └── GetPhotosEndToEndShould.kt │ ├── main │ │ ├── res │ │ │ ├── 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 │ │ │ ├── drawable-hdpi │ │ │ │ ├── ic_search_white_24dp.png │ │ │ │ ├── ic_share_white_24dp.png │ │ │ │ ├── baseline_photo_camera_white_24.png │ │ │ │ └── baseline_photo_library_white_24.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── ic_search_white_24dp.png │ │ │ │ ├── ic_share_white_24dp.png │ │ │ │ ├── baseline_photo_camera_white_24.png │ │ │ │ └── baseline_photo_library_white_24.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── ic_share_white_24dp.png │ │ │ │ ├── ic_search_white_24dp.png │ │ │ │ ├── baseline_photo_camera_white_24.png │ │ │ │ └── baseline_photo_library_white_24.png │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── ic_search_white_24dp.png │ │ │ │ ├── ic_share_white_24dp.png │ │ │ │ ├── baseline_photo_camera_white_24.png │ │ │ │ └── baseline_photo_library_white_24.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ ├── ic_search_white_24dp.png │ │ │ │ ├── ic_share_white_24dp.png │ │ │ │ ├── baseline_photo_camera_white_24.png │ │ │ │ └── baseline_photo_library_white_24.png │ │ │ ├── xml │ │ │ │ └── provider_paths.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── menu │ │ │ │ ├── menu_detail.xml │ │ │ │ └── menu_photo_list.xml │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── layout │ │ │ │ ├── fragment_description.xml │ │ │ │ ├── activity_photo_list.xml │ │ │ │ ├── item_photo.xml │ │ │ │ └── activity_detail.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── me │ │ │ │ └── jorgecastillo │ │ │ │ └── kodein │ │ │ │ ├── common │ │ │ │ ├── GenericFileProvider.kt │ │ │ │ ├── router │ │ │ │ │ ├── Navigator.kt │ │ │ │ │ └── PhotoAppNavigator.kt │ │ │ │ ├── domain │ │ │ │ │ ├── model │ │ │ │ │ │ └── Photo.kt │ │ │ │ │ ├── error │ │ │ │ │ │ └── Error.kt │ │ │ │ │ ├── interactor │ │ │ │ │ │ ├── UseCase.kt │ │ │ │ │ │ ├── Invoker.kt │ │ │ │ │ │ └── UseCaseInvoker.kt │ │ │ │ │ └── repository │ │ │ │ │ │ ├── Policies.kt │ │ │ │ │ │ ├── PhotosNetworkDataSource.kt │ │ │ │ │ │ └── PhotosLocalDataSource.kt │ │ │ │ ├── view │ │ │ │ │ ├── ImageViewExtensions.kt │ │ │ │ │ └── BitmapExtensions.kt │ │ │ │ ├── log │ │ │ │ │ ├── Logger.kt │ │ │ │ │ └── AndroidLogger.kt │ │ │ │ ├── data │ │ │ │ │ ├── network │ │ │ │ │ │ ├── http │ │ │ │ │ │ │ ├── HttpClient.kt │ │ │ │ │ │ │ └── HeadersInterceptor.kt │ │ │ │ │ │ ├── mapper │ │ │ │ │ │ │ └── PhotoMappers.kt │ │ │ │ │ │ ├── UnsplashService.kt │ │ │ │ │ │ ├── UnsplashPhotosDataSource.kt │ │ │ │ │ │ └── model │ │ │ │ │ │ │ └── Models.kt │ │ │ │ │ └── local │ │ │ │ │ │ └── InMemoryPhotosDataSource.kt │ │ │ │ ├── presenter │ │ │ │ │ └── BasePresenter.kt │ │ │ │ └── di │ │ │ │ │ ├── ActivityModule.kt │ │ │ │ │ ├── InjectedActivity.kt │ │ │ │ │ └── AppModules.kt │ │ │ │ ├── PhotosApp.kt │ │ │ │ ├── detail │ │ │ │ ├── description │ │ │ │ │ ├── DescriptionPresenter.kt │ │ │ │ │ ├── di │ │ │ │ │ │ └── descriptionFragmentModule.kt │ │ │ │ │ ├── customview │ │ │ │ │ │ └── CustomTextView.kt │ │ │ │ │ └── DescriptionFragment.kt │ │ │ │ ├── domain │ │ │ │ │ └── interactor │ │ │ │ │ │ └── GetPhoto.kt │ │ │ │ ├── di │ │ │ │ │ └── detailActivityModule.kt │ │ │ │ ├── presenter │ │ │ │ │ └── DetailPresenter.kt │ │ │ │ └── view │ │ │ │ │ └── DetailActivity.kt │ │ │ │ └── photoslist │ │ │ │ ├── domain │ │ │ │ ├── interactor │ │ │ │ │ └── GetPhotos.kt │ │ │ │ └── repository │ │ │ │ │ └── PhotosRepository.kt │ │ │ │ ├── di │ │ │ │ └── photoListActivityModule.kt │ │ │ │ ├── presenter │ │ │ │ └── PhotoListPresenter.kt │ │ │ │ └── view │ │ │ │ ├── PhotosAdapter.kt │ │ │ │ └── PhotoListActivity.kt │ │ └── AndroidManifest.xml │ ├── androidTest │ │ └── java │ │ │ └── me │ │ │ └── jorgecastillo │ │ │ └── kodein │ │ │ ├── OverridesRule.kt │ │ │ ├── recyclerview │ │ │ ├── RecyclerItemViewAssertion.java │ │ │ └── RecyclerViewInteraction.java │ │ │ └── PhotoListActivityShould.kt │ └── sharedTest │ │ └── java │ │ └── BlockingUseCaseInvoker.kt ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── assets ├── list.png └── detail.png ├── course ├── 1 │ ├── Slides.pdf │ ├── Slides.md │ └── Script.md ├── 2 │ ├── Slides.pdf │ ├── Slides.md │ └── Script.md ├── 3 │ └── Script.md ├── 4 │ ├── Slides.pdf │ ├── Slides.md │ └── Script.md ├── 5 │ ├── Slides.pdf │ ├── Slides.md │ └── Script.md ├── 6 │ ├── Slides.pdf │ ├── scopes.png │ ├── Slides.md │ └── Script.md ├── 7 │ └── Script.md ├── 8 │ ├── Slides.pdf │ ├── Slides.md │ └── Script.md ├── 9 │ └── Script.md ├── 10 │ ├── Slides.pdf │ ├── Slides.md │ └── Script.md ├── 11 │ └── Script.md ├── 12 │ ├── detail.png │ ├── detail_share.png │ └── Script.md ├── 13 │ ├── Slides.pdf │ ├── scopes.png │ ├── scopes_app_context.png │ ├── scopes_context_per_scope.png │ ├── Slides.md │ └── Script.md ├── 14 │ ├── Slides.pdf │ ├── scopes.png │ ├── Slides.md │ └── Script.md ├── 15 │ ├── Slides.pdf │ ├── scopes_custom_views.png │ ├── Slides.md │ └── Script.md ├── 16 │ ├── Slides.pdf │ ├── architecture.png │ ├── architecture_side_effects.png │ ├── Slides.md │ └── Script.md └── 17 │ ├── Slides.pdf │ ├── ui_tests.png │ ├── ui_tests_mocks.png │ ├── Slides.md │ └── Script.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── gradle.properties ├── gradlew.bat ├── README.md └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline 2 | -------------------------------------------------------------------------------- /assets/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/assets/list.png -------------------------------------------------------------------------------- /assets/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/assets/detail.png -------------------------------------------------------------------------------- /course/1/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/1/Slides.pdf -------------------------------------------------------------------------------- /course/10/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/10/Slides.pdf -------------------------------------------------------------------------------- /course/12/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/12/detail.png -------------------------------------------------------------------------------- /course/13/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/13/Slides.pdf -------------------------------------------------------------------------------- /course/13/scopes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/13/scopes.png -------------------------------------------------------------------------------- /course/14/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/14/Slides.pdf -------------------------------------------------------------------------------- /course/14/scopes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/14/scopes.png -------------------------------------------------------------------------------- /course/15/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/15/Slides.pdf -------------------------------------------------------------------------------- /course/16/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/16/Slides.pdf -------------------------------------------------------------------------------- /course/17/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/17/Slides.pdf -------------------------------------------------------------------------------- /course/2/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/2/Slides.pdf -------------------------------------------------------------------------------- /course/4/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/4/Slides.pdf -------------------------------------------------------------------------------- /course/5/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/5/Slides.pdf -------------------------------------------------------------------------------- /course/6/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/6/Slides.pdf -------------------------------------------------------------------------------- /course/6/scopes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/6/scopes.png -------------------------------------------------------------------------------- /course/8/Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/8/Slides.pdf -------------------------------------------------------------------------------- /course/17/ui_tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/17/ui_tests.png -------------------------------------------------------------------------------- /course/12/detail_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/12/detail_share.png -------------------------------------------------------------------------------- /course/16/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/16/architecture.png -------------------------------------------------------------------------------- /course/17/ui_tests_mocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/17/ui_tests_mocks.png -------------------------------------------------------------------------------- /course/13/scopes_app_context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/13/scopes_app_context.png -------------------------------------------------------------------------------- /course/15/scopes_custom_views.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/15/scopes_custom_views.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /course/13/scopes_context_per_scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/13/scopes_context_per_scope.png -------------------------------------------------------------------------------- /course/16/architecture_side_effects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/course/16/architecture_side_effects.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-hdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_share_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-mdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_share_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xhdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/baseline_photo_camera_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-hdpi/baseline_photo_camera_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/baseline_photo_camera_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-mdpi/baseline_photo_camera_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/baseline_photo_library_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-hdpi/baseline_photo_library_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/baseline_photo_library_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-mdpi/baseline_photo_library_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/baseline_photo_camera_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xhdpi/baseline_photo_camera_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/baseline_photo_library_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xhdpi/baseline_photo_library_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/baseline_photo_camera_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxhdpi/baseline_photo_camera_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/baseline_photo_library_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxhdpi/baseline_photo_library_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/baseline_photo_camera_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxxhdpi/baseline_photo_camera_white_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/baseline_photo_library_white_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JorgeCastilloPrz/AndroidKodeinSample/HEAD/app/src/main/res/drawable-xxxhdpi/baseline_photo_library_white_24.png -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/GenericFileProvider.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common 2 | 3 | import android.support.v4.content.FileProvider 4 | 5 | class GenericFileProvider : FileProvider() 6 | -------------------------------------------------------------------------------- /app/src/main/res/xml/provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /course/14/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Injecting Fragments" 6 | 7 | --- 8 | 9 | ![inline](scopes.png) 10 | -------------------------------------------------------------------------------- /course/15/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Injecting Custom Views" 6 | 7 | --- 8 | 9 | ![inline](scopes_custom_views.png) 10 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Dec 04 12:57:40 CET 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 7 | -------------------------------------------------------------------------------- /course/17/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Injecting Mocks on your UI tests" 6 | 7 | --- 8 | 9 | ![inline](ui_tests.png) 10 | 11 | --- 12 | 13 | ![inline](ui_tests_mocks.png) 14 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/router/Navigator.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.router 2 | 3 | /** 4 | * Navigation contract used by the app. It can be implemented for different frameworks like Android. 5 | */ 6 | interface Navigator { 7 | 8 | fun goToDetail(photoId: String) 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/domain/model/Photo.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.domain.model 2 | 3 | data class Photo(val id: String, 4 | val url: String, 5 | val author: String, 6 | val description: String?, 7 | val created_at: String) 8 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/domain/error/Error.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.domain.error 2 | 3 | /** 4 | * Domain errors will fit with one of these types. 5 | */ 6 | sealed class Error { 7 | class NetworkConnection : Error() 8 | class ServerError : Error() 9 | 10 | abstract class FeatureError : Error() 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/domain/interactor/UseCase.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.domain.interactor 2 | 3 | import arrow.core.Either 4 | import me.jorgecastillo.kodein.common.domain.error.Error 5 | 6 | abstract class UseCase where ReturnType : Any { 7 | 8 | abstract fun run(params: Params): Either 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/domain/repository/Policies.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.domain.repository 2 | 3 | /** 4 | * Any repo is prone to apply different cache policies per query method. 5 | */ 6 | sealed class CachePolicy { 7 | object NetworkFirst : CachePolicy() 8 | object LocalFirst : CachePolicy() 9 | object LocalOnly : CachePolicy() 10 | object NetworkOnly : CachePolicy() 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/domain/interactor/Invoker.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.domain.interactor 2 | 3 | import arrow.core.Either 4 | import me.jorgecastillo.kodein.common.domain.error.Error 5 | 6 | interface Invoker { 7 | 8 | fun execute(useCase: UseCase, 9 | params: Params, 10 | onResult: (Either) -> Unit) 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/view/ImageViewExtensions.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.view 2 | 3 | import android.support.annotation.DrawableRes 4 | import android.widget.ImageView 5 | import com.squareup.picasso.Picasso 6 | 7 | fun ImageView.load(url: String, @DrawableRes placeHolderRes: Int = 0) { 8 | Picasso.get() 9 | .load(url) 10 | .also { 11 | if (placeHolderRes != 0) it.placeholder(placeHolderRes) 12 | } 13 | .into(this) 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_photo_list.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /course/6/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Scoped Injection: Activity Scope" 6 | 7 | --- 8 | 9 | ## Scopes define: 10 | ### When dependencies __are instantiated__ 11 | ### When dependencies __can be released__ 12 | 13 | --- 14 | 15 | ## __Two__ (or more) scopes: 16 | ### __Application Scope__ 17 | ### __Activity Scope__ 18 | ### (Fragment Scope?) 19 | 20 | --- 21 | 22 | ![inline](scopes.png) 23 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/log/Logger.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.log 2 | 3 | /** 4 | * Logger contract. It can be implemented in different ways for different 5 | * technologies. 6 | */ 7 | interface Logger { 8 | fun log(tag: String, level: Level = Level.Verbose, message: String) 9 | 10 | sealed class Level { 11 | object Info : Level() 12 | object Debug : Level() 13 | object Warning : Level() 14 | object Error : Level() 15 | object Verbose : Level() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/data/network/http/HttpClient.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.data.network.http 2 | 3 | import me.jorgecastillo.kodein.BuildConfig 4 | import okhttp3.Interceptor 5 | import okhttp3.OkHttpClient 6 | 7 | fun httpClient(headersInterceptor: Interceptor, loggingInterceptor: Interceptor): OkHttpClient = 8 | OkHttpClient.Builder().addNetworkInterceptor(headersInterceptor).also { 9 | if (BuildConfig.DEBUG) { 10 | it.addInterceptor(loggingInterceptor) 11 | } 12 | }.build() 13 | -------------------------------------------------------------------------------- /course/5/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Lazy Injections" 6 | 7 | --- 8 | 9 | * bindings work as __deferred functions__ 10 | 11 | ```kotlin 12 | bind() with singleton { AndroidLogger(ctx) } 13 | ``` 14 | * Runs whenever `{ AndroidLogger(ctx) }` gets called. 15 | 16 | ## __Everything is lazy__ by default! 17 | 18 | --- 19 | 20 | ## Laziness ensures __memory__ integrity 21 | ### Avoid blowing your memory heap 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/PhotosApp.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein 2 | 3 | import android.app.Application 4 | import android.support.annotation.VisibleForTesting 5 | import me.jorgecastillo.kodein.common.di.appModule 6 | import org.kodein.di.Kodein 7 | import org.kodein.di.KodeinAware 8 | 9 | class PhotosApp : Application(), KodeinAware { 10 | 11 | @VisibleForTesting 12 | var overrideBindings: Kodein.MainBuilder.() -> Unit = {} 13 | 14 | override val kodein = Kodein.lazy { 15 | import(appModule(applicationContext)) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/detail/description/DescriptionPresenter.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.detail.description 2 | 3 | import me.jorgecastillo.kodein.common.presenter.BasePresenter 4 | 5 | class DescriptionPresenter(private val description: String) : BasePresenter() { 6 | 7 | interface View : BasePresenter.View { 8 | fun renderDescription(descriptionText: String): Unit 9 | } 10 | 11 | override fun resume(view: View) { 12 | super.resume(view) 13 | view.renderDescription(description) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /course/13/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | ![inline](scopes.png) 6 | 7 | --- 8 | 9 | ![inline](scopes_app_context.png) 10 | 11 | --- 12 | 13 | ![inline](scopes_context_per_scope.png) 14 | 15 | --- 16 | 17 | ## __Runtime exception!__ :boom: 18 | ## "There's a binding already defined for the type Interceptor" 19 | 20 | 21 | ### __Not allowed:__ Binding two different implementations to one type. 22 | 23 | --- 24 | 25 | ## __Binding overrides__ to the rescue! 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/data/network/mapper/PhotoMappers.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.data.network.mapper 2 | 3 | import me.jorgecastillo.kodein.common.data.network.model.PhotoDto 4 | import me.jorgecastillo.kodein.common.data.network.model.author 5 | import me.jorgecastillo.kodein.common.domain.model.Photo 6 | 7 | fun List.toDomain(): List = this.map { it.toDomain() } 8 | 9 | fun PhotoDto.toDomain(): Photo = Photo( 10 | this.id, 11 | this.urls.regular, 12 | this.author, 13 | this.description, 14 | this.created_at) 15 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/domain/repository/PhotosNetworkDataSource.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.domain.repository 2 | 3 | import arrow.core.Either 4 | import me.jorgecastillo.kodein.common.domain.error.Error 5 | import me.jorgecastillo.kodein.common.domain.model.Photo 6 | 7 | /** 8 | * The data source contracts are part of the domain layer. Their implementations belong to the data 9 | * layer. 10 | */ 11 | interface PhotosNetworkDataSource { 12 | 13 | fun getAll(): Either> 14 | 15 | fun getPhoto(photoId: String): Either 16 | } 17 | -------------------------------------------------------------------------------- /course/16/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Testing your architecture" 6 | ## (__mock injection__) 7 | 8 | --- 9 | 10 | ## Thinking before testing 🤔 11 | 12 | * Be smart about __the scope__ 13 | * Be smart about __the tests you wanna write__ 14 | * Be smart about __how to add value__ 15 | 16 | --- 17 | 18 | ## What would I test? 19 | 20 | ## __Remove frameworks__! 21 | 22 | --- 23 | 24 | ![inline](architecture.png) 25 | 26 | --- 27 | 28 | ![inline](architecture_side_effects.png) 29 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/detail/description/di/descriptionFragmentModule.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.detail.description.di 2 | 3 | import me.jorgecastillo.kodein.detail.description.DescriptionPresenter 4 | import org.kodein.di.Kodein 5 | import org.kodein.di.generic.bind 6 | import org.kodein.di.generic.provider 7 | 8 | /** 9 | * Specific android scoped module for the detail activity. 10 | */ 11 | fun descriptionFragmentModule(description: String) = Kodein.Module("descriptionFragmentModule") { 12 | bind() with provider { DescriptionPresenter(description) } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Android Kodein 3 | Settings 4 | Something went wrong when loading images. 5 | Something went wrong when loading the picture. 6 | Pic by: 7 | on 8 | Unsplash 9 | The author has not provided any description for this photo. 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/photoslist/domain/interactor/GetPhotos.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.photoslist.domain.interactor 2 | 3 | import me.jorgecastillo.kodein.common.domain.interactor.UseCase 4 | import me.jorgecastillo.kodein.common.domain.model.Photo 5 | import me.jorgecastillo.kodein.photoslist.domain.repository.PhotosRepository 6 | 7 | class GetPhotos(private val photosRepository: PhotosRepository) : 8 | UseCase>() { 9 | 10 | override fun run(params: Params) = photosRepository.getAll() 11 | 12 | data class Params(val page: Int, val query: String) 13 | } 14 | -------------------------------------------------------------------------------- /course/2/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "First steps" 6 | 7 | --- 8 | 9 | Artifacts: 10 | 11 | * `kodein-di-generic-jvm`: __no type erasure__ 12 | * `kodein-di-erased-jvm`: __suffers type erasure__ 13 | * `kodein-di-erased-native`: iOS... 14 | * `kodein-di-erased-js`: Javascript support 15 | * `kodein-di-framework-android`: syntax and utilities 16 | 17 | --- 18 | 19 | Interested on: 20 | 21 | * `kodein-di-generic-jvm`: __no type erasure__ 22 | * `kodein-di-framework-android`: syntax and utilities 23 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/log/AndroidLogger.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.log 2 | 3 | import android.util.Log 4 | 5 | /** 6 | * Android Logger implementation using Logcat. 7 | */ 8 | class AndroidLogger : Logger { 9 | override fun log(tag: String, level: Logger.Level, message: String) { 10 | when (level) { 11 | Logger.Level.Info -> Log.i(tag, message) 12 | Logger.Level.Debug -> Log.d(tag, message) 13 | Logger.Level.Warning -> Log.w(tag, message) 14 | Logger.Level.Error -> Log.e(tag, message) 15 | Logger.Level.Verbose -> Log.v(tag, message) 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/detail/domain/interactor/GetPhoto.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.detail.domain.interactor 2 | 3 | import me.jorgecastillo.kodein.common.domain.error.Error 4 | import me.jorgecastillo.kodein.common.domain.interactor.UseCase 5 | import me.jorgecastillo.kodein.common.domain.model.Photo 6 | import me.jorgecastillo.kodein.photoslist.domain.repository.PhotosRepository 7 | 8 | class PhotoNotFound : Error.FeatureError() 9 | 10 | class GetPhoto(private val photosRepository: PhotosRepository) : UseCase() { 11 | 12 | override fun run(params: String) = photosRepository.getPhoto(params) 13 | } 14 | -------------------------------------------------------------------------------- /course/4/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Your first injection" 6 | 7 | --- 8 | 9 | ## ~~Directly depending on external frameworks~~ 10 | ## __Abstract away__ those pieces 11 | 12 | --- 13 | 14 | ```kotlin 15 | class Logger { 16 | fun log(tag:String, message: String): Unit { 17 | Log.d(tag, message) 18 | } 19 | } 20 | 21 | // Other pieces of the architecture: 22 | logger.log("Use Case", "Photos not found!") 23 | ``` 24 | 25 | --- 26 | 27 | ## Wrong: We're strongly __depending on the Android framework__! 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | misc.xml 2 | workspace.xml 3 | thumbdrawable.svg 4 | Thumbs.db 5 | 6 | .DS_Store 7 | 8 | # Built application files 9 | *.apk 10 | *.ap_ 11 | *.iml 12 | 13 | # Files for the Dalvik VM 14 | *.dex 15 | 16 | # Java class files 17 | *.class 18 | 19 | # Generated files 20 | bin/ 21 | gen/ 22 | 23 | # Gradle files 24 | .gradle/ 25 | build/ 26 | reports/ 27 | 28 | # Local configuration file (sdk path, etc) 29 | local.properties 30 | 31 | # Proguard folder generated by Eclipse 32 | proguard/ 33 | 34 | # Log Files 35 | *.log 36 | 37 | # Intellij IDEA files 38 | /.idea 39 | 40 | # Captures from IDE (Layout Inspector, ...) 41 | /captures 42 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/presenter/BasePresenter.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.presenter 2 | 3 | /** 4 | * Presenter contract. It must have a view assigned to the type T. 5 | */ 6 | open class BasePresenter { 7 | 8 | /** 9 | * Base view contract. All views on this app will have a loading progressbar. 10 | */ 11 | interface View { 12 | fun showLoading(): Unit 13 | fun hideLoading(): Unit 14 | } 15 | 16 | var view: T? = null 17 | 18 | open fun resume(view: T) { 19 | this.view = view 20 | } 21 | 22 | open fun pause() { 23 | this.view = null 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/router/PhotoAppNavigator.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.router 2 | 3 | import android.content.Context 4 | import me.jorgecastillo.kodein.detail.view.DetailActivity 5 | 6 | /** 7 | * Android Router implementation. We're implementing an interface so we can easily switch the router 8 | * by a mock in tests when needed. We don't want to have android dependencies on our unit tests. 9 | */ 10 | class PhotoAppNavigator(private val context: Context) : Navigator { 11 | override fun goToDetail(photoId: String) { 12 | context.startActivity(DetailActivity.getIntent(context, photoId)) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 32dp 3 | 24dp 4 | 16dp 5 | 8dp 6 | 4dp 7 | 2dp 8 | 9 | 16sp 10 | 14sp 11 | 16sp 12 | 12sp 13 | 14 | 80dp 15 | 0.5dp 16 | 6dp 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/domain/repository/PhotosLocalDataSource.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.domain.repository 2 | 3 | import arrow.core.Either 4 | import me.jorgecastillo.kodein.common.domain.error.Error 5 | import me.jorgecastillo.kodein.common.domain.model.Photo 6 | 7 | /** 8 | * The data source contracts are part of the domain layer. Their implementations belong to the data 9 | * layer. 10 | */ 11 | interface PhotosLocalDataSource { 12 | 13 | fun getAll(): Either> 14 | 15 | fun getPhoto(photoId: String): Either 16 | 17 | fun save(photos: List): Unit 18 | 19 | fun save(photo: Photo): Unit 20 | } 21 | -------------------------------------------------------------------------------- /app/src/androidTest/java/me/jorgecastillo/kodein/OverridesRule.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import org.junit.rules.ExternalResource 5 | import org.kodein.di.Kodein 6 | 7 | /** 8 | * Used to retrieve test application before every test and override dependencies. 9 | */ 10 | class OverridesRule(private val bindings: Kodein.MainBuilder.() -> Unit = {}) : ExternalResource() { 11 | 12 | private fun app(): PhotosApp = 13 | InstrumentationRegistry.getTargetContext().applicationContext as PhotosApp 14 | 15 | override fun before() { 16 | app().overrideBindings = bindings 17 | } 18 | 19 | override fun after() { 20 | app().overrideBindings = {} 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/detail/di/detailActivityModule.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.detail.di 2 | 3 | import me.jorgecastillo.kodein.detail.domain.interactor.GetPhoto 4 | import me.jorgecastillo.kodein.detail.presenter.DetailPresenter 5 | import org.kodein.di.Kodein 6 | import org.kodein.di.generic.bind 7 | import org.kodein.di.generic.instance 8 | import org.kodein.di.generic.provider 9 | 10 | /** 11 | * Specific android scoped module for the detail activity. 12 | */ 13 | fun detailActivityModule(photoId: String) = Kodein.Module("detailActivityModuleDI") { 14 | bind() with provider { GetPhoto(instance()) } 15 | bind() with provider { DetailPresenter(instance(), photoId, instance()) } 16 | } 17 | -------------------------------------------------------------------------------- /course/8/Slides.md: -------------------------------------------------------------------------------- 1 | autoscale: true 2 | footer: [caster.io - Dependency Injection in Android using Kodein](https://www.caster.io) 3 | slidenumbers: true 4 | 5 | # "Transitive Dependencies" 6 | 7 | --- 8 | 9 | * PhotosListActivity bindings: 10 | 11 | ```kotlin 12 | fun photoListActivityModule() = Kodein.Module { 13 | bind() with provider { PhotoListPresenter() } 14 | } 15 | ``` 16 | 17 | * Presenter can be instantiated and injected on the activity 18 | 19 | --- 20 | 21 | * But what if presenter had __its own dependencies__? 22 | 23 | ```kotlin 24 | fun photoListActivityModule() = Kodein.Module { 25 | bind() with provider { PhotoListPresenter(????, ????, ????) } 26 | } 27 | ``` 28 | 29 | * __Nested bindings__ to the rescue! 30 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/photoslist/di/photoListActivityModule.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.photoslist.di 2 | 3 | import me.jorgecastillo.kodein.photoslist.domain.interactor.GetPhotos 4 | import me.jorgecastillo.kodein.photoslist.presenter.PhotoListPresenter 5 | import org.kodein.di.Kodein 6 | import org.kodein.di.generic.bind 7 | import org.kodein.di.generic.instance 8 | import org.kodein.di.generic.provider 9 | 10 | /** 11 | * Specific android scoped module for the photos list activity. 12 | */ 13 | fun photoListActivityModule() = Kodein.Module("PhotoListActivityModuleDI") { 14 | bind() with provider { GetPhotos(instance()) } 15 | bind() with provider { PhotoListPresenter(instance(), instance(), instance()) } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_description.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #51bba8 4 | #85cfc2 5 | #3d9c8b 6 | #d14b63 7 | #da6e82 8 | #864BC3 9 | #aa81d5 10 | #212121 11 | #cccccc 12 | #dddddd 13 | #ffffff 14 | #CCffffff 15 | #ff6c6c 16 | #32eb91 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/me/jorgecastillo/kodein/common/data/network/http/HeadersInterceptor.kt: -------------------------------------------------------------------------------- 1 | package me.jorgecastillo.kodein.common.data.network.http 2 | 3 | import okhttp3.Interceptor 4 | import okhttp3.Response 5 | import okhttp3.logging.HttpLoggingInterceptor 6 | 7 | fun loggingInterceptor(): HttpLoggingInterceptor = 8 | HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) 9 | 10 | class HeadersInterceptor : Interceptor { 11 | override fun intercept(chain: Interceptor.Chain): Response { 12 | val request = chain.request() 13 | .newBuilder() 14 | .addHeader("Accept-Version", "v1") 15 | .addHeader("Authorization", "Client-ID e0bf5ecd991a987cde8231a5bfecc35bbb4ddf282d3a5a44091cf606b916dbb8") 16 | .build() 17 | return chain.proceed(request) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |