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