Before reading this checkout this sources:
Download & import: Kotlin Code Style for Android Studio
Code organized by packages as stated in architecture guide.
Class structure has following order:
If constructor arguments doesn't fit in one line or it has class scoped arguments each argument should be states on a new line.
If class extends from View
class it will be good to use JvmOverloads
annotation.
For regular classes companion object
should be at the top of class (exceptions – model classes, dagger modules). Companion object follows the same structure rules as a regular classes.
In first place should be declared fields that will be injected.
Methods declaration ordering has following rules:
It's preferred for all methods to have explicitly specified type.
Expression body is preferred when it is possible to use it.
Nested classes should be at the end of parent class (view state is exception). inner
keyword should be avoided if it possible.
Nested classes shouldn't be referenced without parent.
Model classes follows the general rules for classes.
If model class supposed to be used in network call it should have @SerializedName
on each valuable field.
Also developer should keep in mind that Gson ingonres Kotlin default values.
Data classes should be used only on demand. So if there is a class that is response wrapper and it won't be used or created manually there is no reason to use data class
keyword.
Global extensions should be placed in file with name: original class name + Extensions
suffix on appropriate code layer. Also global extension should solve "global" problems.
MVP pattern implemented on top of Android Architecture components that make it possible to preserve view state on configuration changes.
View state is usually represented by State
object with addition one shoot methods. If some atom cannot be represented by state it should be expressed as one shoot action.
View State
object is implemented with sealed class
with required payload.
Dependency injection works on top of Dagger.
It is good to split modules by logic. Predefined modules names are:
domain
+ data
+ remote
+ cache
layerspresentation
+ view
layerWe prefer @Inject
annotation on constructor instead of manual constructor call in module.
We prefer private val
modificator for constructor injected properties and internal lateinit var
for fields. Also it is prefered to use internal
in dagger modules and components.
Prefer to use guards in methods instead of nested if. Guards should be on top of method.
Horizontal alignment is allowed only for named arguments.
Do not use ConstraintLayout
for every layout. It's better to use simpler layout if it possible.
Support & AndroidX views is preferred over default ones.
Prefixes:
bg_
prefix for all background or foreground resourcesic_
prefix for all iconscolor_
prefix for color resourcesSuffixes:
_selector
suffix for selectors_ripple
suffix for ripple variants resources (only for projects with minSdk < 21)Prefixes & suffixes can be combined.
Prefixes:
activity_
for activity layoutfragment_
for fragment layoutlayout_
for include
layoutsitem_
for recycler view itemsview_
for custom viewAll resources names after prefixes described above should also contain feature name.
Examples:
activity_restaurants_map.xml
layout_restaurant_header.xml
All clickable views should have visual response on clicks. By default you can use ?selectableItemBackground
or ?selectableItemBackgroundBorderless
for square and round views. Or you should create your own background drawable with ripple effect for this view if it necessary.