1. 程式人生 > >Kotlin入門(33)運用擴充套件屬性

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