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)運用擴展屬性