继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

使用Kotlin Android开发记下的一些心得

繁花不似锦
关注TA
已关注
手记 337
粉丝 50
获赞 241

一周前开始学习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语言插件

5b97d1710001fdb305000195.jpg


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

//必须
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更简洁容易理解!

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

原文链接:http://www.apkbus.com/blog-914653-68407.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP