任务Runnable定义了一个可以独立运行的代码片段,通常用于界面控件的延迟处理,比如有时为了避免同时占用某种资源造成冲突,有时则是为了反复间隔刷新界面从而产生动画效果。运行一个任务也有多种形式,既可在UI线程中调用处理器对象的post或者postDelayed方法,也能另外开启分线程来执行Runnable对象。那么在运行任务之前,必须事先声明该任务的对象,然后才能由调用者执行该任务。Kotlin代码声明Runnable对象有四种方式,分别对应不同的业务场景,接下来就依次阐述Runnable对象的四种声明方式:

第一种:内部类

内部类方式是最循规蹈矩的,在代码里先书写一个继承自Runnable的内部类,再重写它的run方法,填入具体的业务逻辑处理。以最常见的计数器为例子,每隔一秒便在界面上显示加一后的计数结果,使用内部类方式进行变化的话,就是以下的Kotlin代码:

    private val handler = Handler()private var count = 0inner private class Counter : Runnable {override fun run() {count++tv_result.text = "当前计数值为:$count"handler.postDelayed(this, 1000)}}

然后在Activity页面的onCreate方法中加上下面一行代码,命令执行这个计数任务:

    handler.post(Counter())

第二种:匿名内部类

内部类的方式最正规,无疑也是最啰嗦的。由于这个计数任务只在页面打开时启动,因此并不需要对其显式构造,只要在定义内部类时顺便声明任务实例即可。此时的声明代码便从内部类方式变成了匿名内部类方式,采取Kotlin编码的话注意使用关键字object占位,表示这是一个匿名内部类,完整的Kotlin代码如下所示:

    private val counter = object : Runnable {override fun run() {count++tv_result.text = "当前计数值为:$count"handler.postDelayed(this, 1000)}}

因为定义内部类的同时就声明了任务实例,所以处理器直接运行该实例即可启动任务:

    handler.post(counter)

内部类与匿名内部类这两种方式,其实内部都拥有类的完整形态,故而它们的run方法允许使用关键字this指代这个人物类,示例代码中的“handler.postDelayed(this, 1000)”意思是间隔一秒之后重复执行自身任务。正因为能够重复执行任务,所以这两种方式可用于持续刷新界面的动画效果。

第三种:匿名函数

前面的两种内部类实现方式,拥有类的完整形态意味着必须显式重写run方法,可是这个任务类肯定且只能重写run方法,即使开发者不写出来,run方法也是逃不掉的。早在第一章,当时为了演示Kotlin代码的间接性,举了一个例子“按钮对象.setOnClickListener { 点击事件的处理代码 }”,这种写法正是采取了Lamba表达式,直接把点击事件接口的唯一方法onClick给省略掉。因此,本节的任务对象也可使用类似的写法,只要说明该对象是Runnable类型,则多余的run方法就能如愿去除。下面是个将任务对象改写后的Kotlin代码:

    private val counter = Runnable {count++tv_result.text = "当前计数值为:$count"}

显而易见,上述的counter仍是Runnable类型,于是处理器依旧运行该实例即可启动任务:

    handler.post(counter)

不过这种写法去掉run方法是有代价的,虽然表面上代码变得简洁,但是并不拥有类的完整结构,其内部的this关键字不再表示任务类自身,而是表示宿主类即Activity活动类了。鉴于这点变化,该方式内部不可再调用处理器的post或者postDelayed方法,意味着此时任务实例无法重复调用自身。因此,采取了匿名函数方式的任务对象,适用于不需要重复刷新的场合。

第四种:匿名实例

注意到前面的counter是个经过等号赋值的任务对象,既然这样,不如直接把等号右边的表达式塞进post方法,就像下面的Kotlin代码那样:

    //第1点:在post方法中直接填写Runnable对象的定义代码handler.post(Runnable {count++tv_result.text = "当前计数值为:$count"})

上面的代码还可以进一步精简,因为post方法只能输入Runnable类型的参数,所以括号内部的Runnable纯属多余;另外,post方法有且仅有一个输入参数,于是圆括号嵌套大括号稍显繁琐。把这两个冗余之处分别删除与合并,得到了匿名实例版的Kotlin代码:

    //第2点:如果该任务只需执行一次,则可采用匿名实例的方式,直接嵌入任务的执行代码handler.post {count++tv_result.text = "当前计数值为:$count"}

上述去掉圆括号的办法,只适合post方法这种仅有一个参数的调用,如果其它方法存在多个输入参数如postDelayed方法,则外层的圆括号仍需予以保留,此时大括号及其内部代码就作为一个函数参数传入。恢复了圆括号的Kotlin调用代码如下所示:

    //第3点:如果是延迟执行任务,则可将匿名实例作为postDelayed的输入参数handler.postDelayed({count++tv_result.text = "当前计数值为:$count"}, 1000)

匿名实例方式直接把任务代码写在调用函数之中,意味着这段任务代码无法被其他地方调用,所以它的适用场景更加狭小。匿名函数虽然无法重复调用,但是尚且允许在不同地方多次调用,而匿名实例只能在它待过的地方昙花一现,因此还是要根据实际的业务要求来选择合适的任务方式。

点此查看Kotlin入门教程的完整目录

__________________________________________________________________________
打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。

Kotlin入门(29)任务Runnable相关推荐

  1. Kotlin入门教程——目录索引

    Kotlin是谷歌官方认可的Android开发语言,即将发布的Android Studio 3.0版本也会开始内置Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初And ...

  2. Kotlin入门(14)继承的那些事儿

    上一篇文章介绍了类对成员的声明方式与使用过程,从而初步了解了类的成员及其运用.不过早在<Kotlin入门(12)类的概貌与构造>中,提到MainActivity继承自AppCompatAc ...

  3. Kotlin入门(5)字符串及其格式化

    上一篇文章介绍了数组的声明和操作,包括字符串数组的用法.注意到Kotlin的字符串类也叫String,那么String在Java和Kotlin中的用法有哪些差异呢?这便是本文所要阐述的内容了. 首先要 ...

  4. Kotlin入门(33)运用扩展属性

    进行App开发的时候,使用震动器要在AndroidManifest.xml中加上如下权限: <!-- 震动 --><uses-permission android:name=&quo ...

  5. Kotlin入门(32)网络接口访问

    手机上的资源毕竟有限,为了获取更丰富的信息,就得到辽阔的互联网大海上冲浪.对于App自身,也要经常与服务器交互,以便获取最新的数据显示到界面上.这个客户端与服务端之间的信息交互,基本使用HTTP协议进 ...

  6. Kotlin入门(31)JSON字符串的解析

    json是App进行网络通信最常见的数据交互格式,Android也自带了json格式的处理工具包org.json,该工具包主要提供了JSONObject(json对象)与JSONArray(json数 ...

  7. Kotlin入门(30)多线程交互

    Android开发时常会遇到一些耗时的业务场景,比如后台批量处理数据.访问后端服务器接口等等,此时为了保证界面交互的及时响应,必须通过线程单独运行这些耗时任务.简单的线程可使用Thread类来启动,无 ...

  8. Kotlin入门(28)Application单例化

    Application是Android的又一大组件,在App运行过程中,有且仅有一个Application对象贯穿应用的整个生命周期,所以适合在Application中保存应用运行时的全局变量.而开展 ...

  9. Kotlin入门(26)数据库ManagedSQLiteOpenHelper

    共享参数毕竟只能存储简单的键值对数据,如果需要存取更复杂的关系型数据,就要用到数据库SQLite了.尽管SQLite只是手机上的轻量级数据库,但它麻雀虽小.五脏俱全,与Oracle一样存在数据库的创建 ...

最新文章

  1. CRF算法中辅助概念 团 极大团 最大团
  2. mysql选定数据库_mysql数据库学习――2,数据库的选定,创建,删除和变更_MySQL...
  3. UVALive 3905 Meteor (扫描线)
  4. meta标签的使用方法(PC端)
  5. 【OpenJudge - noi - 7624】山区建小学(dp)
  6. Invitation Cards POJ 1511
  7. docker k8s helm常用命令梳理
  8. 【Java】反射、枚举、Lambda表达式
  9. c语言实验答案周信东综合程序设计,周信东主编最新版-C语言程序设计基础实验一实验报告.doc...
  10. Lumerical---FDTD仿真区域设置问题
  11. mysql多表查询去重复数据_SQL重复记录查询 查询多个字段、多表查询、删除重复记录的方法...
  12. undo歌词中文音译_Undo - Sanna nielsen帮我看看这歌词翻译对么
  13. 设置TextView滚动
  14. 微信公众号如何设置开发者密码(APPSecret)?
  15. 新手如何学习学嵌入式开发?
  16. java ext.dirs_关于-Djava.ext.dirs使用问题
  17. Python接口测试实战1(下)- 接口测试工具的使用
  18. 悼念512汶川大地震遇难同胞——重建希望小学 ( )
  19. webpackvue-cli快速构建
  20. 软件工程师杰夫的个人营销实例(十分钟看完系列)

热门文章

  1. 吴恩达深度学习神经网络基础编程作业Building your Deep Neural Network Step by Step
  2. 正点原子操作过程中芯片总是出错
  3. 如何用1年时间获得3年成长?
  4. 第三:Python发送邮件时中文附件下载乱码
  5. java was datasource_mybatis默认的数据源连接池(PooledDataSource和UnPooledDataSource)
  6. [Ext JS 4] 实战之Load Mask - 在Grid Reconfigure的使用状况
  7. android pdf生成 路径,android – 如何从指向PDF文档的URI获取文件路径?
  8. 引入SpringBoot Jpa依赖后,项目出现警告
  9. 计算机组成微程序操作码怎么写,计算机组成原理学习笔记——控制器
  10. 小米互联通信服务_时隔六年,小米NFC碰碰贴复活,碰一下自动亮灯、联网、投屏...