原创

Kotlin Android开发一些心得

一周前开始学习kotlin,现在已经在项目中开发使用了。我目前负责的项目老代码非常多,之前的java代码已经有十多万行了。所以即便使用了kotlin,也只是在新建文件的代码里使用,老代码继续用java。kotlin的好处就是完全兼容java,java调用kotlin,kotlin基本上无阻碍。

先说说为什么要转kotlin

  • Google已经明确kotlin为第一官方语言。我相信Google的决意,就像当初毫不犹豫的抛弃eclipse转向as。kotlin已经是不可避免的大势所趋了。

  • Kotlin与java代码完全兼容。使用kotlin就好像只是增加了一个库。打个比方,Rxjava比较难上手吧,不懂Rxjava的人看Rxjava像看天书,更不知从何写起。kotlin学起来比Rxjava简单的多。

  • 作为一名程序猿,我是非常追求代码的简洁高效。在代码简洁上,kotlin简直是神器,太和我心意了。由于要兼容低版本,之前就一直在用java的lambda表达式插件,但是很多java8的特性还是用不了。kotlin全部能做到,而且更好。在易理解的基础上,能用1行代码搞定的事我绝不会写两行。用了kotlin,我自己写的很多基础函数都用不着了。真正的Enjoy Coding!

也说一下目前遇到的一些问题

  • 由于集成了kotlin包,apk会增大约0.5M。这看你的项目是否能接受了,我觉得还行。

  • 目前没发现什么大坑。在java-kotlin互相调用时要小心,koltin如果不注明,是强制不为空的。如果你的java代码有良好的习惯,出入参都注明了@Nullable @Nonnull,就没什么问题了

安装与配置

参考kotlin官网

我的android studio 没有升级3.0预览版,使用的还是2.3版本。

  • 首先更新kotlin语言插件

Kotlin Android开发一些心得

屏幕快照 2017-05-30 下午6.17.38.png

  • 工程里添加如下插件配置

//必须 apply plugin: 'kotlin-android'  //快捷的findviewfindid操作,建议加上 apply plugin: 'kotlin-android-extensions'

然后是依赖路径

buildscript {  //可能由于androidstudio版本原因,老提示我这里使用1.1.2-3版本,最新应该是1.1.2-4,根据提示来即可  ext.kotlin_version = '1.1.2-3'  repositories {      jcenter()      //阿里的maven仓国内镜像,如果gradle下载很慢,建议使用该仓库      maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }      mavenCentral()   }  dependencies {      classpath 'com.android.tools.build:gradle:2.3.2'      classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"      classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"  } }

最后是编译依赖的仓库,用着这个就行了。

compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

注意几点:

  • 如果之前使用了依赖于注解的库如Dragger,databinding等,需要额外的配置,详情请参考官网

  • Anko 是一个封装了很多android操作的库,比如ui操作、异步操作、数据库操作等等。不过我目前觉得还用不着,就没加。感兴趣的同学可以自己去添加。

ok, 可以进入kotlin世界了!

我主要是参考了这本书 《Kotlin for Android developers》 ,加上一些自己的理解。内容不多,看几遍就记得差不多了。刚学习kotlin时可以下载下来,使用时随时查阅。

Koltin的类

kotlin的变量申明 val 是不可变变量,相当于java里的final。var是可变变量,一般情况尽量使用val 。如果使用var一般都需要判空

val i = 7 //自动类型推导 val str:String = "hello"//也可以显式的指明类型 var name: String? = null//可变变量一般要注意使用安全操作符? ,使用时都要加上? val length = name?.length

这里有个小坑,如果没加?传入了空参数是,kotlin会强制判空抛异常。

只要是Java语言有交互的参数,除非是100%确定不为空,否则请务必都加上安全操作符?。

类继承

class CustomView(context: Context?, attrs: AttributeSet?) : View(context, attrs)

构造函数

额外添加一个属性name

class CustomView(val name:String, context: Context?, attrs: AttributeSet?) : View(context, attrs)

添加其他构造函数

class CustomView(context: Context?, attrs:AttributeSet?) : TextView(context, attrs){     constructor(name: String, context: Context?, attrs:AttributeSet?):this(context, attrs) {         text = name     } }

另外,kotlin不需要new操作符了,创建类直接调用其构造方法,就像使用普通函数那样。

val view = CustomView(context, attrs)

Kotlin的方法

方法申明差不多,动手写一下很快就明白了。

默认参数特别好用! 终于可以不用写一大堆同名函数了

动态方法扩展相当于将一大堆Util换种写法

比如异步加载图片的封装,java这样写

  public static void setImageUriAsync(@NonNull ImageView iv, String uri, boolean round) {     ...       }    public static void setImageUriAsync(@NonNull ImageView iv, String uri) {         setImageUriAsync(iv, uri, false);  }

kotlin这样写:

fun ImageView.setImageUrlAsync(url: String?, isRound: Boolean = false) {     ... }

调用时就当做imageview的普通方法使用即可

iv.setImageUrlAsync(url) iv.setImageUrlAsync(url, true)

注意一点

在java里,所有的方法都要在声明在类里,一般一个类也只能有一个pulic方法。kotlin的方法可以独立放在类外面,左右全局使用,比如前面提到ImageView扩展方法就要单独放在类外部。kotlin一个文件可以申明多个全局方法,声明多个public类。就是说,很多东西都能放在kotlin一个文件里。

Koltin的Null处理

使用安全操作符?可以省略很多无意义判空操作

不多说,直接上代码,一看就都明白了。

以前这样写

    if (adapter != null) {         List list = adapter.getDatas();                 if (list != null) {                     for (CmdNotice it :list) {                         if (it.getId() == notice.getId()) {                             it.setStatus(notice.getStatus());                             adapter.notifyDataSetChanged();                             break;                         }                     }                 }         }

现在这样写

adapter?.datas?.firstOrNull({ it.id == notice.id })?.let {                     it.status = notice.status                     adapter?.notifyDataSetChanged()                 }

静态常量,静态函数,单例

如果一个类里都是静态常量和静态函数,直接在最外面写

object Const{     val MSG_1 = 1     fun getCurrentDate():Date{         return Date()     } }

如果是在普通类里有静态变量,以及单例,这样写

class MyCache{     companion object {         val TYPE = 1 //常量         val instance = MyCache() //单例     } }

这样调用

MyCache.TYPE MyCache.instance

kotlin的inline(内联)函数

内联函数与一般的函数不同,在编译时会做替换,少了普通函数调用的压栈出栈,更高效。因为是替换,所以可以识别传入的泛型

比如

inline fun  getClassName():String{     return T::class.java.name }

直接这样调用

val name = getClassName()

可以传入代码块,比如一个异步线程操作的代码块

object MyExecutor{     val instance: ExecutorService = Executors.newCachedThreadPool() } inline fun doSync(crossinline block: () -> Unit) {     MyExecutor.instance.execute { block() } }  //调用如下。 传入的block代码块可以直接放在函数后面的{}里。     override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.main)         doSync{             //Code: Request network         }     }

Kotlin基础库里大量的便捷操作以及Anko库里很多操作都是使用inline函数完成的。常用的when, apply, let,以及对list数组封装的各种操作firstOrNull,filter等都是内联函数完成的。

Koltin函数需要传入的代码块可以直接放在函数名的大括号里,不需要再用小扩号包起来。这样的话,很多调用就非常简洁

比如Anko库里的async, uiThread ,异步操作的写法比Rxjava简单的多!

        async{             //Do step1 cost time             uiThread { toast("complete step1") }             //Do step2 cost time             uiThread {  toast("complete step2")}         }

而且其写法很巧妙,只保存了外部Activity的弱引用,如果在异步执行过程中Activity销毁了uiThread则不会调用,防止内存泄漏。

FindViewById

由于有了插件kotlin-android-extensions.

Activity里可以这样写,不需要在额外申明TextView变量了。所以注意xml文件里id的命名使用驼峰写法

        setContentView(R.layout.main)         tvTitle.setOnClickListener { toast("hello") }

Adapter里这样写, ViewHolder完全不需要了

   view.tvName.text = notice.name    view.tvNumber.text = ""    view.ivIcon.setImageUrlAsync(icon, true)

其他

注意在kotlin中== 相当于java中的equal函数,=== 相当于java中的==。不过一般情况加==就够了。kotlin中没有基本类型,所有的如Int,Long都是对象。

kotlin中没有三元操作符。可以用if else,或者 ?:代替。

java:

String a = result?"true":"false"

kotlin:

val a = if (result) "true" else "false"

?:表示先判断前面是否为空,为空的话就返回后面的

java:

String b = (a==null)?a:"true"

kotlin:

val b=a?:"true"

因为都是基于JVM,Kotlin的所有操作java当然都能做到,但是kotlin更简洁容易理解!

先到这里,如有问题欢迎指正,大家共同进步!

正文到此结束
Loading...