This is an Android Studio template for apps written in Kotlin, using Clean Architecture, MVP and packaging by feature
src/
├── com.my.package/
│ ├── di/
│ │ ├── component/
│ │ │ ├── AppComponent.kt
│ │ │ ├── BaseFeatureComponent.kt
│ │ │ ├── YourFeatureComponent.kt
│ │ │ └── ...
│ │ ├── module/
│ │ │ ├── AppModule.kt
│ │ │ ├── YourFeatureModule.kt
│ │ │ └── ...
│ │ ├── qualifier/
│ │ │ └── AppQualifier.kt
│ │ └── scope/
│ │ │ ├── AppScope.kt
│ │ │ ├── YourFeatureScope.kt
│ │ │ └── ...
│ └── presentation/
│ ├── base/
│ │ ├── BaseActivity.kt
│ │ ├── BaseContract.kt
│ │ ├── BaseFragment.kt
│ │ ├── BaseIntentBuilder.kt
│ │ ├── BasePresenter.kt
│ │ └── ViewTypeDelegate.kt
│ ├── common/
│ │ ├── AppSchedulerProvider.kt
│ │ ├── ObservableView.kt
│ │ └── SchedulerProvider.kt
│ ├── somefeature/
│ │ ├── YourFeatureActivity.kt
│ │ ├── YourFeatureContract.kt
│ │ ├── YourFeatureFragment.kt
│ │ └── YourFeaturePresenter.kt
│ └── ...
└── res/
└── layout/
├── activity_some_feature.xml
└── fragment_some_feature.xml
-
Your app must be written in Kotlin
-
The generated files will be located in the kotlin source set
app/src/main/kotlin
Add this to your module
build.gradlesourceSets { main.java.srcDirs += 'src/main/kotlin' } -
You must use:
AppCompatfor the base classesimplementation "com.android.support:appcompat-v7:$appCompatVersion" implementation "com.android.support:design:$designVersion"- RxJava 2 for the
SchedulerProviderused in the presentersimplementation "io.reactivex.rxjava2:rxjava:$rootProject.ext.rxJavaVersion" implementation "io.reactivex.rxjava2:rxandroid:$rootProject.ext.rxAndroidVersion" - Dagger 2 for dependency injection.
BaseContract,BaseActivityandBaseFragmentare already implement an easy way of injecting your dependenciesimplementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion"
- Copy the
CleanArchitectureMVPdirectory to$ANDROID_STUDIO_FOLDER$/Contents/plugins/android/lib/templates/ - Restart Android Studio
- Copy the
CleanArchitectureMVPdirectory to$ANDROID_STUDIO_FOLDER$\plugins\android\lib\templates\ - Restart Android Studio
- In Android Studio, select the
Projectview - Right click and select
New>Clean + MVP>Base and Common. This will generate thepresentation/baseandpresentation/commonpackages and files
- In Android Studio, select the
Projectview - Right click and select
New>Clean + MVP>DependencyInjection - App. This will generate thedi/component,di/module,di/qualifieranddi/scopepackages and files. - In you
Applicationfile create a companion object:
companion object {
lateinit var appComponent: AppComponent
}
- In the
onCreatemethod add the following:
appComponent = DaggerAppComponent.builder()
.appModule(AppModule(this))
.build()
- In Android Studio, select the
Projectview - Right click and select
New>Clean + MVP>DependencyInjection - Feature. This will generate acomponent, amoduleand ascopefor the feature - In your
AppComponentinterface, add the following method:
fun instantiateComponent(module: YourFeatureModule): YourFeatureComponent
Where YourFeatureModule should be replaced by the generated class in di/module and YourFeatureComponent should be replaced by the generated class in di/component
4. In YourFeatureComponent add the fun inject() methods required to inject your activities and fragments that depend on that component
5. In your Application class, add the following:
5.1 a property to hold the component reference private var yourFeatureComponent: YourFeatureComponent? = null
5.2 the following methods to get and release the component:
fun instantiateYourFeatureComponent(activity: FragmentActivity): YourFeatureComponent? {
if (featureComponent == null) {
featureComponent = appComponent.instantiateComponent(FeatureModule(activity))
}
return featureComponent
}
fun releaseFeatureComponent() {
featureComponent = null
}
Where YourFeatureComponent should be replaced by the generated class in di/component and the method names should be meaningful, the first starting with instantiante and the second one starting with release
- In Android Studio, select the
Projectview - Right click and select
New>Clean + MVP>Feature - Presentation - Type in the
Nameof the feature, e.g.TopUp,Checkout,PaymentMethods - Everything else is done automatically, following the guidelines and convetions defined by the team
- You can uncheck the boxes in case you don't want to create:
5.1 the
Contractand thePresenter5.2 theActivitywith layout 5.3 theFragmentwith layout - If you created an activity don't forget to add it to the
AndroidManifest - If you created an activity and/or a fragment, remember to check the
TODOs.
- Don't do it
- They use
ApacheFreeMarker(.ftlextension) - This is probably the best docummentation online. Other than that there are several github repositories, this tutorial and this article
- Since
srcDirandsrcOutare only mapped to thejava source set, there is a property inglobals.xml.ftlnamedkotlinMainSourceSetwhich doessrcOut?replace('java','kotlin')and is used inrecipe.xml.ftl - Since
classToResourcewould convertSomeCompositeNametosome_composite_nameand that doesn't follow the recommended convetion for package names, there are several?replace('_', '')inrecipe.xml.ftland in*.kt.ftlfiles located at[TEMPLATE]\root\src\app_package - Since
applicationIdSuffixinbuild.gradlewould afftect where the files are generated there is a property inglobals.xml.ftlnamedkotlinMainSourceSetwhich doessrcOut?replace('.debug|.staging|.systest', '', 'r')that is used inrecipe.xml.ftland a property namedmainSourceSetPackagewhich doespackageName?replace('.debug|.staging|.systest', '', 'r')and is used in all*.kt.ftlat[TEMPLATE]\root\src\app_package - In the
?replace()function the first argument can be a regex, and if that's the case than the funcion takesras the third argument