[关闭]
@946898963 2020-07-09T15:27:50.000000Z 字数 2853 阅读 964

Kotlin编码规范

Kotlin


基础的规范可以查看官方规范,这里记录了在官方规范之外的一些推荐用法。

代码规范

1.属性命名使用驼峰命名法,不使用匈牙利命名法

  1. 正例:class Person(val id: Int, val name: String)
  2. 反例:class Person(val mId: Int, val mName: String)

2.属性代理命名添加合适的前缀

  1. 正例:var observableIsFront by Delegates.observable(false)
  2. 反例:var isFront by Delegates.observable(false)

一些属性代理给属性绑定了特定的行为,如果命名上不做区分,查看代码的时候很可能漏掉属性的特定行为。lazy这类常用并且不影响代码逻辑的属性代理可以不加前缀。

常用的属性代理:

  1. Delegates.observable
  2. Delegates.vetoable

3.不要在Fragment的onDestroyView之后使用id操作View;不要重复使用id获取子View

在Fragment的onDestroyView生命周期之后ViewMap已经q清除,使用id操作View会导致空指针异常;每次使用id获取子View都会调用一次find过程,正确的做法应该是获取一次后用变量存起来。

4.被Kotlin调用的Java方法参数加上@NotNull和@Nullable

  1. 正例:public UIBaseDialogBuilder setTitle(@NotNull String title)
  2. 反例:public UIBaseDialogBuilder setTitle(String title)

注解可以被Kotlin识别,避免Java代码未判空导致的NPE

5.常量使用const声明

6.尽量使用扩展方法代替Util类

7.避免使用!!

正例:

  1. someField?.let { doSomethingAbout(it) }
  2. // or
  3. val field = someField
  4. if (someOtherCondition && field != null) {
  5. doSomethingAbout(field)
  6. }

反例:

  1. if (someField != null) {
  2. doSomethingAbout(someField!!)
  3. }

在一些情况下,即使判断了属性非空,也不能把属性当成是非空属性来使用(考虑到多线程因素,判空代码块内的属性也不一定非空)。使用?或者局部变量来保证代码执行时属性不为空。

唯一可以使用!!的地方是想通过抛出异常的方式处理特殊case,例如Fragment中拿到的activity是null。

8.优先使用val

理由参考最小化可变性

9.多行链式调用格式

正例:

  1. Observable.just(10)
  2. .map { it * 3 } // one line
  3. .filter { // line break in case of multiple lines
  4. val rand = Random()
  5. it % rand.nextInt(10) == 0
  6. }
  7. .map(Int::toFloat) // method reference
  8. .withLatestFrom(Observable.just("foo")) { num, hoge -> num to foo } // Use rx-kotlin
  9. .subscribe ({ // start a new line in subscribe block if it implements `onError`
  10. print(it)
  11. }, {
  12. print(it)
  13. })

反例:

  1. Observable.just(10)
  2. .map {
  3. it * 3
  4. }
  5. .filter {
  6. val rand = Random()
  7. it % rand.nextInt(10) == 0
  8. }
  9. .map { it.toFloat() }
  10. .withLatestFrom(Observable.just("foo"), BiFunction { num: Float, foo: String -> num to foo })
  11. .subscribe ({ print(it) }, { print(it) })

10.类型别名

对一些很复杂的类型和Lambda表达式使用类型别名

正例:

  1. typealias Restaurant = Organization<(Currency, Coupon?) -> Sustenance>
  2. typealias CompileStatusObserver = (status: Pair<CompileStatus, Int>) -> Unit

性能相关

1.将需要重复调用的非内联的捕获Lambda表达式声明为inline

注:捕获 Lambda 表达式指在表达式内部访问了表达式外的非静态变量或者对象的表达式,非捕获 Lambda 表达式反之

2.使用const关键字在伴生对象中声明常量

3.避免在局部函数中捕获外部变量

4.Java中的基础类型在Kotlin中声明为非空类型,同样的原因优先使用IntArray而不是Array

5.接受数组参数时优先使用数组类型参数而不是vararg

6.考虑代理属性带来的性能开销,避免使用泛型委托

7.使用lazy延迟初始化,考虑指定为LazyThreadSafetyMode.NONE避免双重校验锁带来的性能损失

Reference:

https://jakewharton.com/just-say-no-to-hungarian-notation/

https://google.github.io/styleguide/javaguide.html#s5.1-identifier-names

https://www.kotlincn.net/docs/reference/coding-conventions.html

https://github.com/Quoc-DEV/quoc-dev.github.io/wiki/Kotlin-Conventions-for-Android

https://medium.com/@BladeCoder/exploring-kotlins-hidden-costs-part-1-fbb9935d9b62

https://medium.com/@BladeCoder/exploring-kotlins-hidden-costs-part-2-324a4a50b70

https://medium.com/@BladeCoder/exploring-kotlins-hidden-costs-part-3-3bf6e0dbf0a4

https://docs.google.com/document/d/1IxoedON4CCI3E0MvYCZlsoF4j7CewbfWq5ODPgM1oio/edit

https://jiapengcai.gitbooks.io/effective-java/content/di-4-zhang-ff1a-lei-he-jie-kou/di-17-tiao-ff1a-shi-ke-bian-xing-zui-xiao-hua.html

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注