android-ktx 已發佈,你尚未用過 Kotlin?

昨天,大神爲他們的新做悄悄的點個贊。而後,就在圈子裏面泛起已一圈一圈的漣漪。今天我來蹭下熱點,簡單介紹下這個庫。html

android-ktx

截止寫這文章的時候,數據已是這個樣子。大神果真是大神啊,基本上搞Android 開發的,都會 flow 一下他,就像混黑社會的,總要拜關二爺。可能有些小夥伴兒就是點個 star ,也沒有仔細看相關內容。java

WX20180207-111410@2x.png

這個庫是來幹什麼的呢?android

A set of Kotlin extensions for Android app development. The goal of Android KTX is to make Android development with Kotlin more concise, pleasant, and idiomatic. It is an explicit goal of this project to not add any new feature to the existing Android APIs.git

這裏說的超級清楚了,這是一套用於Android應用開發的 Kotlin 擴展。目的就是爲了讓咱們使用 Kotlin 進行簡潔、愉悅、慣用地 Android 開發,它一個明確的目的就是不向現有的 API 添加新的功能。github

簡單的說就是,這個庫就是一個 Kotlin 寫的包裝庫,讓你可以開心、快速地完成項目開發,它只是包裝,不會增長新的功能。數據庫

因此,咱們如今的代碼能夠愈來愈短,愈來愈簡潔。不屑的人可能就會說,不就又搞了一堆語法糖嘛,這玩意兒不過如此。總有一種全天下的功夫他都會,可是他就懶得寫。閉包

進入正文,先看看這個庫目前提供了那些類的包裝。 app

WX20180207-113238@2x.png

其實還算挺多的。我瞭解下來,以爲多少真的不重要,關鍵是得實用,真的解決開發過程當中實實在在存在的痛點。ide

實用 Java 開發過程當中,總有一些代碼看着就讓人頭痛。好比說最基本的設置點擊事件。ViewTreeObserver 相關監聽,Bundle 建立和存值、SharedPreferences 存值、數據庫 Cursor 的操做、Hander 發消息處理消息 Intent 跳轉,Runnable 等等,這些代碼真沒技術含量,可是爲了實現這裏方法,你必須寫出一大堆模版式的方法或者建立所屬的對象,感受就像每次都在祭天,神聖,流程必須高度一致(玩笑話)。函數

接下來對比看一下吧。

//before
 val observer = textView.viewTreeObserver
    observer.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            val maxLines = textView.height / textView.lineHeight
            textView.maxLines = maxLines
            textView.viewTreeObserver.removeOnPreDrawListener(
                    this)
            return false
        }
    })
    //after
textView.doOnPreDraw {
        val maxLines = textView.height / textView.lineHeight
        textView.maxLines = maxLines
    }

//before
val sp = getEditor(context)
sp.putFloat(key, value)
sp.apply()   


//after
getSharedPreferences(context).edit {
        putFloat(key, value)
    }
複製代碼

記得剛剛入門那會兒,使用 SharedPreferences 忘記調用 apply() 或者 commit() 方法,致使結果不生效。因此使用這套庫以後,你徹底能夠沒必要再去擔憂這些細節問題了。

看完了簡單例子,是否是以爲包裝一下以後代碼又是少了一大截呢?接着看下內部是具體怎麼實現的。

/**
 * Performs the given action when the view tree is about to be drawn.
 */
inline fun View.doOnPreDraw(crossinline action: (view: View) -> Unit) {
    val vto = viewTreeObserver
    vto.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            action(this@doOnPreDraw)
            when {
                vto.isAlive -> vto.removeOnPreDrawListener(this)
                else -> viewTreeObserver.removeOnPreDrawListener(this)
            }
            return true
        }
    })
}
複製代碼

經過上面能夠看到,代碼仍是之前那些繁瑣的代碼,固定的代碼已經成爲模版,而你具體要作的就經過這個 action 方法回調給你實現。

這裏着重介紹三個關鍵字,inlinecrossinline noinline

inline: 咱們都知道,在 Java 裏面,不能直接進行方法賦值的,都得面向對象。好比說點擊事件的 ClickListener ,其實最後咱們就須要的 onClick() 這個方法,可是每次卻不得不將其包裝爲一個 ClickListener 對象。當咱們在使用 inline 關鍵詞做用在方法上以後,編譯器能夠直接發出如下代碼,而不是再爲參數建立一個函數對象而後生成一個調用,這聽着可不要太爽呢。

crossinline: 說完 inline 以後,若是咱們做爲方法參數的函數並非直接在方法內部被調用,而是在一個 lambda 表達式中或者在一個內部類中,這種狀況呢,咱們據須要使用 crossinline 來聲明該方法,告訴編譯器它是能夠經過的。有點兒像 Java 中內部類調用了外部的臨時變量,該變量得聲明爲 final 同樣。

noinline: 說完了 crossinline ,咱們固然也能知道咱們有時候也要限制這個函數式參數的做用域,這時候就須要使用 noinline 來聲明。這就有點兒像 @Nullale @NonNull 同樣,聲明後 IDE 自動爲你檢測,並警告你。

關鍵字說完,其實就能夠結束了,是的,就是這麼簡單,這裏再簡單提下閉包 Closure。Kotlin 裏面閉包用的超級多,最直觀的感覺就是你能夠少些不少小括號。

觀察下面這個方法調用,原本是調用的 doOnPreDraw() 方法,可是它的小括號卻不見了。

textView.doOnPreDraw {
        val maxLines = textView.height / textView.lineHeight
        textView.maxLines = maxLines
    }
複製代碼

完整一點兒它應該是這樣的:

textView.doOnPreDraw({
        view -> 
        
    })
複製代碼

產生上面的寫法,是由於若是你的方法參數就一個,而且它是一個函數表達式,那麼就能夠省略掉小括號,保持簡潔易讀。你不覺小括號又跟上大括號看起來是有點兒詭異嗎?

這種閉包實際上是十分常見的,好比說你再看下 build.gradle 配置文件,是否是所有都是這套路?

signingConfigs {
    release {
        storeFile file("../release.jks")
        keyPassword gradle.password
    }
    debug {
        storeFile file("../debug.keystore")
        storePassword "android「
    }
}
複製代碼

最後學以至用,最開始我就說了,很討厭寫跳轉 Activity 的方法,真的很煩,大概就是這樣的:

val intent = Intent(context, TopicDetailActivity::class.java)
    intent.putExtra(Constants.ID, id)
    context!!.startActivity(intent)
複製代碼

而後本身擼一個相似的方法:

inline fun <T> startActivityIntent(context: Context?, clazz: Class<T>, action: (intent: Intent) -> Unit) {
    if (context == null) {
        return
    }
    val intent = Intent(context, clazz)
    action(intent)
    context.startActivity(intent)
}
複製代碼

接着你就能夠開心的調用啦:

startActivityIntent(context, TopicDetailActivity::class.java, {
        it.putExtra(Constants.ID, id)
    })
複製代碼

說到這裏,本文應該結束。除了這個剛由 Google 推出的 Kotlin 擴展庫,Kotlin 官方老早就出過相關擴展來方便咱們開發,也是生怕咱們一開始不適應,不使用。https://github.com/Kotlin/anko

回到題目,你若是到限制真尚未用過 Kotlin ,那你真的要考慮嘗試用來它來開發,玩一玩,由於它支持 lambda,支持閉包,代碼更簡潔。並且它獲得了Google 的大力支持,就和剛開始的 Android Studio同樣,可謂是根正苗紅。

對了,目前這個庫目前並非最終正式版本,可能會有 API 的規範性改動或移除,直接用於項目的小夥伴要作好心理準備,畢竟吃螃蟹有風險。

參考資料

Kotlin functions 沒事兒多看看官方文檔吧。@Parcelize 用起來也超級爽。

相關文章
相關標籤/搜索