Codingstyle file can be found at TODO URL
To install the file, open Android Studio Settings and go to Editor > Code Style > Kotlin, then click the gear menu and choose Import Scheme....
All projects should follow the correct style guidelines.
Note: Following plugin is helpful in sorting methods in class : https://plugins.jetbrains.com/plugin/11410-android-sorter
This style-guide is somewhat of a mash-up between the existing Kotlin language style guides. The language guidance is drawn from:
All source files must be encoded as UTF-8.
On the whole, naming should follow Java standards, as Kotlin is a JVM-compatible language.
Package names are similar to Java: all lower-case, multiple words concatenated together, without hypens or underscores:
BAD:
com.pulselive.funky_widget
GOOD:
com.pulselive.funkywidget
Written in UpperCamelCase. For example :
AndroidActivity, NetworkHelper, UserFragment, PerActivity
Any classes extending an Android framework component should always end with the component name. For example:
UserFragment, SignUpActivity, RateAppDialog, PushNotificationServer, NumberView
UpperCamelCase helps to seperate the words used to create the name, making it easier to read. Naming classes to end with the framework component makes it super clear as to what the class is used for. For example, if you're looking to make changes to the RegistrationDialog then this naming convention makes it really easy to locate that class.
Written in lowerCamelCase. For example setValue
.
Generally, written in lowerCamelCase. Fields should not be named with Hungarian notation, as Hungarian notation is erroneously thought to be recommended by Google.
Example field names:
class MyClass {
var publicField: Int = 0
val person = Person()
private var privateField: Int?
}
Constant values in the companion object should be written in uppercase, with an underscore separating words:
companion object {
const val THE_ANSWER = 42
}
Written in lowerCamelCase.
Single character values must be avoided, except for temporary looping variables.
In code, acronyms should be treated as words. For example:
BAD:
XMLHTTPRequest
URL: String?
findPostByID
GOOD:
XmlHttpRequest
url: String
findPostById
Do | Don't |
---|---|
setUserId | setUserID |
String uri | String URI |
int id | int ID |
parseHtml | parseHTML |
generateXmlFile | generateXMLFile |
When naming resource files you should be sure to name them using lowercase letters and underscores instead of spaces, for example:
activity_main, fragment_user, item_post
This convention again makes it really easy to locate the specific layout file that you're looking for. Within android studio, the layout package is sorted in alphabetical order meaning that activity, fragment and other layout types becomes grouped - so you know where to begin looking for a file. Other than this, beginning the file name with the component name makes it clear what component/class the layout file is being used for.
Drawable resource files should be named using the ic_ prefix along with the size and color of the asset. For example, white accept icon sized at 24dp would be named:
ic_accept_24dp_white
And a black cancel icon sized at 48dp would be named:
ic_cancel_48dp_black
We use this naming convention so that a drawable file is recognisable by its name. If the colour and size are not stated in the name, then the developer needs to open the drawable file to find out this information. This saves us a little bit of time :)
Other drawable files should be named using the corresponding prefix, for example:
Type | Prefix | Example |
---|---|---|
Selector | selector_ | selector_button_cancel |
Background | bg_ | bg_rounded_button |
Circle | circle_ | circle_white |
Progress | progress_ | progress_circle_purple |
Divider | divider_ | divider_grey |
This convention again helps to group similar items within Android Studio. It also makes it clear as to what the item is used for. For example, naming a resource button_cancel could mean anything! Is this a selector resource or a rounded button background? Correct naming helps to clear any ambiguity that may arise.
When creating selector state resources, they should be named using the corresponding suffix:
State | Suffix | Example |
---|---|---|
Normal | _normal | btn_accept_normal |
Pressed | _pressed | btn_accept_pressed |
Focused | _focused | btn_accept_focused |
Disabled | _disabled | btn_accept_disabled |
Selected | _selected | btn_accept_selected |
Using clear prefixes such as the above helps to make it absolutely obvious as to what a selector state resource is used for. Prefixing resources with the colour or any other identifier again requires the developer to open the selector file to be educated in what the different selector state resources are.
When naming layout files, they should be named starting with the name of the Android Component that they have been created for. For example:
Component | Class Name | Layout Name |
---|---|---|
Activity | MainActivity | activity_main |
Fragment | MainFragment | fragment_main |
Dialog | RateDialog | dialog_rate |
Widget | UserProfileView | view_user_profile |
AdapterView Item | N/A | item_follower |
Note: If you create a layout using the merge tag then the layout_ prefix should be used.
Not only does this approach makes it easy to find files in the directory hierarchy, but it really helps when needing to identify what corresponding class a layout file belongs to.
Menu files do not need to be prefixed with the menu_ prefix. This is because they are already in the menu package in the resources directory, so it is not a requirement.
All resource file names should be plural, for example:
attrs.xml, strings.xml, styles.xml, colors.xml, dimens.xml
When naming fields that reference views, the name of the view should be the last word in the name. For example:
View | Name |
---|---|
TextView | usernameView |
Button | acceptLoginView |
ImageView | profileAvatarView |
RelativeLayout | profileLayout |
We name views in this way so that we can easily identify what the field corresponds to. For example, having a field named user is extremely ambiguous - giving it the name usernameView, userAvatarView or userProfieLayout helps to make it clear exactly what view the field corresponds with.
Only include visibility modifiers if you need something other than the default of public.
BAD:
public val wideOpenProperty = 1
private val myOwnPrivateProperty = "private"
GOOD:*
val wideOpenProperty = 1
private val myOwnPrivateProperty = "private"
Access level modifiers should be explicitly defined for classes, methods and member variables.
Prefer single declaration per line.
GOOD:
username: String
twitterHandle: String
Exactly one class per source file, although inner classes are encouraged where scoping appropriate.
Prefer data classes for simple data holding objects.
BAD:
class Person(val name: String) {
override fun toString() : String {
return "Person(name=$name)"
}
}
GOOD:
data class Person(val name: String)
Indentation is using spaces - never tabs.
Indentation for blocks uses 4 spaces:
GOOD:
for (i in 0..9) {
Log.i(TAG, "index=" + i);
}
Lines should be no longer than 100 characters long. Indentation for line wraps should use 8 spaces.
GOOD:
val widget: CoolUiWidget =
someIncrediblyLongExpression(that, reallyWouldNotFit, on, aSingle, line)
####Where to break The prime directive of line-wrapping is: prefer to break at a higher syntactic level. Also:
- When a line is broken at a non-assignment operator the break comes before the symbol.
- This also applies to the following “operator-like” symbols:
- The dot separator (.).
- The two colons of a member reference (::).
- When a line is broken at an assignment operator the break comes after the symbol.
- A method or constructor name stays attached to the open parenthesis (() that follows it.
- A comma (,) stays attached to the token that precedes it.
- A lambda arrow (->) stays attached to the argument list that precedes it.
####Functions When a function signature does not fit on a single line, break each parameter declaration onto its own line. Parameters defined in this format should use a single indent (+4). The closing parenthesis ()) and return type are placed on their own line with no additional indent.
GOOD:
fun <T> Iterable<T>.joinToString(
separator: CharSequence = ", ",
prefix: CharSequence = "",
postfix: CharSequence = ""
): String {
// …
}
Unlike Java, direct access to fields in Kotlin is preferred.
If custom getters and setters are required, they should be declared following Kotlin conventions rather than as separate methods.
Only trailing closing-braces are awarded their own line. All others appear the same line as preceding code:
BAD:
class MyClass
{
fun doSomething()
{
if (someTest)
{
// ...
}
else
{
// ...
}
}
}
GOOD:
class MyClass {
fun doSomething() {
if (someTest) {
// ...
} else {
// ...
}
}
}
Unlike switch
statements in Java, when
statements do not fall through. Separate cases using commas if they should be handled the same way. Always include the else case.
BAD:
when (anInput) {
1 -> doSomethingForCaseOne()
2 -> doSomethingForCaseOneOrTwo()
3 -> doSomethingForCaseThree()
}
GOOD:
when (anInput) {
1, 2 -> doSomethingForCaseOneOrTwo()
3 -> doSomethingForCaseThree()
else -> println("No case satisfied")
}
Standard annotations should be used - in particular override
. This should appear on the same line as the function declaration.
BAD:
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
}
GOOD:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
}
Constants are defined using the val
keyword, and variables with the var
keyword. Always use val
instead of var
if the value of the variable will not change.
Tip: A good technique is to define everything using val
and only change it to var
if the compiler complains!
When a View in an XML layout does not have any child views, self-closing tags should be used.
GOOD:
<ImageView
android:id="@+id/image_user"
android:layout_width="90dp"
android:layout_height="90dp" />
BAD:
<ImageView
android:id="@+id/image_user"
android:layout_width="90dp"
android:layout_height="90dp">
</ImageView>
All IDs should be prefixed using the name of the element that they have been declared for.
Element | Prefix |
---|---|
ImageView | image_ |
Fragment | fragment_ |
RelativeLayout | layout_ |
Button | button_ |
TextView | text_ |
View | view_ |
All string names should begin with a prefix for the part of the application that they are being referenced from. For example:
Screen | String | Resource Name |
---|---|---|
Registration Fragment | “Register now” | registration_register_now |
Sign Up Activity | “Cancel” | sign_up_cancel |
Rate App Dialog | “No thanks” | rate_app_no_thanks |
If it’s not possible to name the referenced like the above, we can use the following rules:
Prefix | Description |
---|---|
error_ | Used for error messages |
title_ | Used for dialog titles |
action_ | Used for option menu actions |
msg_ | Used for generic message such as in a dialog |
label_ | Used for activity labels |
When defining both Styles & Themes, they should be named using UpperCamelCase. For example:
AppTheme.DarkBackground.NoActionBar
AppTheme.LightBackground.TransparentStatusBar
ProfileButtonStyle
TitleTextStyle
Any Unit Test classes should be written to match the name of the class that the test are targeting, followed by the Test suffix. For example:
Class | Test Class |
---|---|
DataManager | DataManagerTest |
UserProfilePresenter | UserProfilePresenterTest |
PreferencesHelper | PreferencesHelperTest |
All Test methods should be annotated with the @Test
annotation, the methods should be named using the following template:
@Test
public void methodNamePreconditionExpectedResult() { }
So for example, if we want to check that the signUp() method with an invalid email address fails, the test would look like:
@Test
public void signUpWithInvalidEmailFails() { }
-
Variable (Properties, sort by alphabet)
-
Override Functions (Properties): Lifecycle methods first
-
Declared Functions:
- Public Functions (sort by alphabet)
- Private Functions (sort by alphabet)