/ android

Nice meeting #Kotlin

最近开始学习使用 Kotlin 语言进行日常开发,目前首先对我的一个壁纸应用 MyerSplash 的 Android 版本开始下手——想起来年初重写 MyerList 真是白费了啊,重写完还没发布,估计我又得用 Kotlin 再写一次了。

正如官方所说的,Kotlin 跟 Java 有 100% 的互操作性,这意味着项目里可以同时存在 Kotlin 和 Java 代码,两者可以互相调用。而从 Java 转到 Kotlin,其实也并不需要完全重写代码——作为锻炼,重写是一个选项,但是也能直接使用工具把 Java 代码转为 Kotlin 代码:

在搭载 Kotlin 的编程环境后,通过在 Search everywhere 搜索 convert java 这样的关键字就可以找到选项了(或者在 Code 菜单里找,此处就不细说了)。

而且转出来的代码,效果也不错——比如众所周知的 Kotlin 里没有 static field/method,通过这个工具的转换,转换出来的原来的 static field/method 会是在 companion object 里,使用起来就跟调用 static field/method 一样——不过,也不是完完全全一样:

比如一个叫 People.kt 的 Kotlin 类是这样子的:

class People {
    fun walk() {
        
    }

    companion object {
        val TAG = "People"
    }
}

在 Java 里调用 PeopleTAG,是这样子的:

public void getTag(){
    return People.Companion.getTAG();
}

而在 Kotlin 里是这样子的:

fun getTag() = People.TAG

看得出区别了吗?

所以啊,虽然 Kotlin 跟 Java 还是能共存,但是,说实话,为了代码写起来,用起来,看起来更优雅,能用 Kotlin 就用 Kotlin 吧~

哦对了,如果你跟我一样,在项目里有用到 ButterKnife / Realm ,也是有些事情需要注意的。

先说 ButterKnife。

举个栗子,你在一个 Activity 里是这样使用 ButterKnife 的:

class MainActivity : AppCompatActivity() {
    @BindView(R.id.textView)
    var textView: TextView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        ButterKnife.bind(this)
    }
}

然后运行看看,肯定会出错。解决办法是,在 textView 前面,加上 @JvmField 注解,这个注解的官方解释是这样子的:

Instructs the Kotlin compiler not to generate getters/setters for this property and expose it as a field.

说得够清楚了。不过这样的话,textView 就不是一个 property 而是一个 field 里——所以啊,你不能把他当属性用,也就是不能这样子:

@JvmField var textView: TextView? = null
    set(value) {
        field=value
        // do other stuff
    }

看起来有点"退步",不过退一万步说,实在不喜欢这样的话,可以使用 Java 写。另外,不想用 ButterKnife 也不想在 findViewById 上浪费时间,还是能有其他方案的,比如使用 Kotlin Android Extensions

接下来是 Realm。

如果你发现,在执行过程中,抛出以下异常:

is not part of the schema for this Realm

那么,你应该在 gradle 文件里,加入:

dependencies {
    // others
    kapt "io.realm:realm-annotations:3.0.0"
    kapt "io.realm:realm-annotations-processor:3.0.0"
}

并且确保 apply plugin: 'realm-android' 是跟在 apply plugin: 'kotlin-android' 之后。

接下来使用应该没问题了。