Kotlin Style Guide for Android Developers (Part I)

This article covers not only aesthetic formatting issues, but also other types of conventions and standards that Android developers need to know.





The main focus is, first of all, on the rigid rules followed by Google developers everywhere!





At first I thought that the article would be small, but due to the enormous number of code examples, it has grown enough.





So I decided to split it into two parts.





Both parts contain a description of the code standards in the Kotlin programming language.





:





  • , , , ..









  • - , , , , .









().





!





, .





UTF-8 .





, , : + .kt





( enum



) , :





// PhotoAdapter.kt

class PhotoAdapter(): RecyclerView.Adapter<PhotoViewHolder>() {
	// ...
}


// Utils.kt

class Utils {}

fun Utils.generateNumbers(start: Int, end: Int, step: Int) {
	// ...
}

// Map.kt

fun <T, O> Set<T>.map(func: (T) -> O): List<O> = // ...
fun <T, O> List<T>.map(func: (T) -> O): List<O> = // ...
      
      



Kotlin .kt :





  • , ()





  • ,





  • package





  • import





  • (, , )





:





/*
 * Copyright 2021 MyCompany, Inc.
 *
 *
 */
      
      



KDoc :





/** 
 * Copyright 2021 MyCompany, Inc.
 *
 */

// Copyright 2021 MyCompany, Inc.
//
      
      



@file



, use-site target package



:





/*
 * Copyright 2021 MyCompany, Inc.
 *
 */

@file:JvmName("Foo")

package com.example.android
      
      



package



import



:





package com.example.android.fragments  //  

import android.view.LayoutInflater //    
import android.view.View
      
      







import



, .





:





 import androidx.room.*  //    
      
      



Kotlin , , typealias



.





. extension , .









, .





, .





: , ,





, .





ASCII (0x20).





, :









  • Tab





, (\b, \r, \t, \\



) , Unicode (: \u000a



).





, ASCII, Unicode (∞), Unicode (\u221e



).





, :





//  :   
val symbol0 = "∞"	

// :       Unicode 
val symbol1 = "\u221e" // ∞	

// :    ,     
val symbol2 = "\u221e"

// :  Unicode    
return "\ufeff" + content	//    

      
      



!





when



if



( if



else



):





if (str.isEmpty()) return

when (option) {
    0 -> return
    // …
}
      
      



if, for, when



do



while



:





if (str.isEmpty())
    return  //   !

if (str.isEmpty()) {
    return  // OK
}
      
      



:









  • c









  • , , , .





class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        // ...
    }
}
      
      



K&R:





try {
    val response = fetchDogs("https://api.dog.com/dogs")
} catch (e: Exception) {} // 

try {
    val response = fetchDogs("https://api.dog.com/dogs")
} catch (e: Exception) {
} // OK
      
      



if/else



, :





val value = if (str.isEmpty()) 0 else 1  // OK

val value = if (str.isEmpty())	// 
	0
else
	1

val value = if (str.isEmpty()) { 	// OK
	0
} else {
	1
}

      
      



4 . ( ).





(;



)





100 .





:





  • , (: URL)





  • package



    import







  • , shell





:





  • infix .





  • , :





    • (.



      , .?



      )





    • (::



      )









  • (,)







  • (->



    ) lambda





, ( 4 ):





fun makeSomething(
  val param1: String,
  val param2: String,
  val param3: Int
) {

}
      
      



:





override fun toString(): String {
	return "Hello, $name"
}

override fun toString() = "Hello, $name"
      
      



, - - :





fun waitMe() = runBlocking {
	delay(1000)
}
      
      



(=



):





 val binding: ListItemBinding = 
 	DataBindingUtil.inflate(inflater, R.layout.list_item, parent, false)
      
      



get



set



(4 ):





 val items: LiveData<List<Item>>
 	get() = _items
      
      



Read-only :





val javaExtension: String get() = "java"

      
      



:





  • : , ,





    • . ( backing )









  • ()





( ) ASCII :





  • , : if



    , for



    catch



    :





// 
for(i in 1..6) {
}

// OK
for (i in 1..6) {
}
      
      



  • , else



    catch



    :





// 
}else {
}

// OK
} else {
}
      
      



  • :





// 
if (items.isEmpty()){
}

// OK
if (items.isEmpty()) {
}
      
      



  • :





// 
val four = 2+2

// OK
val four = 2 + 2

//        (->)

// 
items.map { item->item % 2 == 0 }

// OK
items.map { item -> item % 2 == 0 }
      
      



  • : (::



    ), (.



    ) range (..



    )





// 
val str = Any :: toString

// OK
val str = Any::toString

// 
item . toString()

// OK
item.toString()

// 
for (i in 1 .. 6) {
		println(i)
}

// OK
for (i in 1..6) {
		println(i)
}
      
      



  • Before a colon ( :



    ) to indicate an extension of a base class or interface, and in an when



    expression for generic types:





// 
class Worker: Runnable

// OK
class Worker : Runnable

// 
fun <T> min(a: T, b: T) where T: Comparable<T>
  
// OK
fun <T> min(a: T, b: T) where T : Comparable<T>
      
      



  • After a colon ( :



    ) or comma ( ,



    )





// 
val items = listOf(1,2)

// OK
val items = listOf(1, 2)

// 
class Worker :Runnable

// OK
class Worker : Runnable
      
      



  • On both sides of the double slash:





// 
var debugging = false//  

// OK
val debugging = false //   
      
      



Conclusion

This article turned out to be quite long, I hope you read it useful.





In the next article: naming, special constructs, and documentation.





Useful links:





  • Kotlin style guide (in English)





  • K&R style





  • Book: Clean Code (Bob Martin)





  • Briefly about the book by Bob Martin





Wait for the next part!












All Articles