Kotlin入门(33)运用扩展属性
进行App开发的时候,使用震动器要在AndroidManifest.xml中加上如下权限:
<!-- 震动 -->
<uses-permission android:name="android.permission.VIBRATE" />
让手机震动的功能用到了震动器Vibrator类,而震动器对象从系统服务VIBRATOR_SERVICE获得,实现该功能的代码很简单,即便用Java书写也只有以下两行代码:
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(3000);
两行代码看起来真没什么好简化的了,因为转换成Kotlin也要下面的两行代码:
//常规做法:从系统服务中获取震动器对象
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.vibrate(3000)
虽然获取震动器的代码并不多,但是这真的真的很难记忆,首先开发者要调用getSystemService一把,接着绞尽脑汁才能想起该服务的名称是VIBRATOR_SERVICE,最后再强制将类型转换为Vibrator。其中又是大写子母又是小写字母还有大小写混合,对于英文不溜的朋友来说,这简直是个灾难。如果只要一个琅琅上口的单词就能代表震动器,那势必为开发者省去了背诵专业英语单词的麻烦。然而两行代码还能怎么优化?倘若改造成工具类获取震动器对象,也不见得一定省事。
不过Kotlin可不会善罢甘休,相反是迎难而上,因为它坐拥扩展函数这个法宝,之前我们多次见识了扩展函数的威力,比如提示窗的toast、提醒对话框的alert等等。当然获取震动器对象也能按照扩展函数来改造,比如给Context添加一个扩展函数getVibrator,则该扩展函数的Kotlin代码示例如下:
//获取震动器
fun Context.getVibrator() : Vibrator {
return getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
接着回到Activity页面代码,实现震动功能只需下面的一行代码了:
//利用扩展函数获得震动器对象
getVibrator().vibrate(3000)
以上代码固然简化了,却仍然不是最简单的写法,看看getVibrator()方法,前面有get后面有括号,都是碍手碍脚的家伙。可去掉括号就不是函数了,而变成了属性,难不成Kotlin啥时多了个扩展属性的用法?其实Kotlin还真的可以实现扩展属性的功能,关键是要利用扩展函数进行移花接木,只要在kt文件中声明一个Context类的新属性,同时定义该属性的get方法(get方法为扩展函数)。如此一来,外部访问该扩展属性之时,编译器会自动调用该属性的get方法,从而通过扩展函数间接实现了扩展属性。接下来依旧以震动器为例,看看如何使用Kotlin代码声明扩展属性vibrator:
//获取震动器
//利用扩展函数实现扩展属性,在Activity代码中即可直接使用vibrator
val Context.vibrator : Vibrator
get() = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
现在回到Activity代码,如下所示只要通过vibrator就能访问震动器的方法了:
//利用扩展函数实现扩展属性,直接使用vibrator即可指代震动器对象
vibrator.vibrate(3000)
当然要想正常访问自定义的扩展函数和扩展属性,需要在活动代码头部加上以下的导入语句:
import com.example.custom.util.vibrator
除了震动器之外,其它从系统服务获得对象的管理器也能照此办理,譬如通知管理器NotificationManager,按照之前的调用方式是下面的Kotlin代码:
val notifyMgr = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notifyMgr.notify(R.string.app_name, notify)
显然通知管理器对象的获取代码更冗长,接下来将其改造为扩展属性的方式,则相应的Context扩展代码如下所示:
//获取通知管理器
//试试在Activity代码中调用“notifier.notify(R.string.app_name, notify)”
val Context.notifier: NotificationManager
get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
然后原来通知管理器的两行代码便缩减为下面的一行代码了:
notifier.notify(R.string.app_name, notify)
举一反三,剩下的来自系统服务的管理器统统运用扩展属性,能够更好地方便将来的开发工作。下面是几个常用管理器的扩展属性实现代码例子:
//获取下载管理器
val Context.downloader: DownloadManager
get() = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
//获取定位管理器
val Context.locator: LocationManager
get() = getSystemService(Context.LOCATION_SERVICE) as LocationManager
//获取连接管理器
val Context.connector: ConnectivityManager
get() = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
//获取电话管理器
val Context.telephone: TelephonyManager
get() = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
//获取无线管理器
val Context.wifi: WifiManager
get() = getSystemService(Context.WIFI_SERVICE) as WifiManager
//获取闹钟管理器
val Context.alarm: AlarmManager
get() = getSystemService(Context.ALARM_SERVICE) as AlarmManager
//获取音频管理器
val Context.audio: AudioManager
get() = getSystemService(Context.AUDIO_SERVICE) as AudioManager
Kotlin入门(33)运用扩展属性的更多相关文章
- Kotlin入门教程——目录索引
Kotlin是谷歌官方认可的Android开发语言,Android Studio从3.0版本开始就内置了Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初Android ...
- Kotlin(2): 优雅地扩展类的方法和属性
欢迎Follow我的GitHub, 关注我的CSDN. 个人博客: http://www.wangchenlong.org/, 最新内容. Kotlin由JetBrains公司推出, 是兼容Java的 ...
- 写给Android开发者的Kotlin入门
写给Android开发者的Kotlin入门 转 https://www.jianshu.com/p/bb53cba6c8f4 Google在今年的IO大会上宣布,将Android开发的官方语言更换为K ...
- Kotlin入门(11)江湖绝技之特殊函数
上一篇文章介绍了Kotlin对函数的输入参数所做的增强之处,其实函数这块Kotlin还有好些重大改进,集中体现在几类特殊函数,比如泛型函数.内联函数.扩展函数.尾递归函数.高阶函数等等,因此本篇文章就 ...
- 关于ES6扩展属性
ES6 let和const let命令 只在代码块作用域内有效 不存在变量提升(不能在申明之前赋值) 暂时性死区(在区域内不受外部变量影响) 不允许重复申明(在相同代码块区域内) 块级作用域 let为 ...
- Kotlin的扩展函数:扩展Android框架(KAD 08)
作者:Antonio Leiva 时间:Jan 11, 2017 原文链接:https://antonioleiva.com/extension-functions-kotlin/ 扩展函数是Kotl ...
- [NewLife.XCode]扩展属性(替代多表关联Join提升性能)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...
- Kotlin入门(28)Application单例化
Application是Android的又一大组件,在App运行过程中,有且仅有一个Application对象贯穿应用的整个生命周期,所以适合在Application中保存应用运行时的全局变量.而开展 ...
- Kotlin入门(13)类成员的众生相
上一篇文章介绍了类的简单定义及其构造方式,当时为了方便观察演示结果,在示例代码的构造函数中直接调用toast提示方法,但实际开发是不能这么干的.合理的做法是外部访问类的成员属性或者成员方法,从而获得处 ...
随机推荐
- [Swift]LeetCode209. 长度最小的子数组 | Minimum Size Subarray Sum
Given an array of n positive integers and a positive integer s, find the minimal length of a contigu ...
- [Swift]LeetCode879. 盈利计划 | Profitable Schemes
There are G people in a gang, and a list of various crimes they could commit. The i-th crime generat ...
- [Swift]LeetCode955. 删列造序 II | Delete Columns to Make Sorted II
We are given an array A of N lowercase letter strings, all of the same length. Now, we may choose an ...
- spark调用hdfsAPI
spark 调用 hdfs API 查询文件名字.删除文件: 获取HDFS上面某个路径下的所有文件的名字 import org.apache.hadoop.conf.Configuration imp ...
- asp.net core 系列 11 配置configuration (下)
四. 文件配置提供程序AddIniFile. AddXmlFile.AddJsonFile FileConfigurationProvider 是从文件系统加载配置的基类. 以下配置提供程序专用于特定 ...
- redis 系列16 持久化 RDB
一.概述 Redis是内存数据库,一旦服务器进程退出,服务器中的数据库内存数据状态也会消失.为了解决这个问题,Redis提供了RDB 持久化功能,这个功能可以将redis在内存中的数据库状态保存到磁盘 ...
- 【朝花夕拾】Android Log篇
前言 从事Android开发的这些年中,经常碰到这样一个现象:同一款app中,往往有好几种风格迥异的log处理方式,有时候会让维护者晕头转向.同时笔者也经常碰带一些模棱两可的问题:Log等级分好几种 ...
- 从零开始学习PYTHON3讲义(七)条件分支和哥德巴赫猜想
<从零开始PYTHON3>第七讲 人生是由无数个选择组成,每个选择都有不同的限定条件.现在来说人生有点早是吧:)不过事实的确是这样的. 程序也充满着选择,满足不同的条件,则运行不同的运算. ...
- 【java多线程】多线程的创建三种方式--笔记
申明:线程的概念以及进程的相关概念,可以参考网络上其他资料,这里只讨论多线程是怎么实现. 一.多线程的简单理解 明白什么是多线程,小生通俗一点的理解为:在一个程序里,我想同时让这个程序完成多个任务. ...
- 三种方法实现CSS三栏布局
本文由云+社区发表 作者:前端林子 本文会分别介绍三种CSS实现三栏布局的方法,可在浏览器中打开查看效果 1.方法一:自身浮动的方法 实现方法:需要左栏向左浮动,右栏向右浮动,中间设左右margin来 ...