Android必備技能之一:Kotlin(一)

20161105_161848.jpg

1、Kotlin前世與今生

  • 寫了太久Java,有沒有發(fā)現(xiàn)其實(shí)你寫了太多冗余的代碼?
  • 你雖然小心翼翼,可總是被QA折騰出來的NullPointerException所頭疼,難道就沒有受夠這種日子么?
  • 直到有一天你發(fā)現(xiàn)自己代碼除了if,else,for循環(huán),竟然沒有任何留戀?

那么我們可以一起來嘗試一下 Kotlin,話說回來了什么是Kotlin呢?

Kotlin是基于JVM新的編程語言,由 JetBrains 開發(fā),可以編譯成java字節(jié)碼,也可以編譯成JavaScript。而JetBrains,作為目前廣受歡迎的Java IDE IntelliJ 的提供商,也在 Apache 許可下已經(jīng)開源其Kotlin 編程語言。

2、Kotlin環(huán)境配置

接下來的我就直接在Android Studio(下面簡稱AS)環(huán)境上面操作,雖然使用IDE IntelliJ也可以實(shí)現(xiàn),但AS上也是對Kotlin支持的,首先下載以下相關(guān)插件(雖然并不是所有插件一次性用到,但建議一次性下載完,后續(xù)就不需要下載了):

  • Kotlin
  • Kotlin Extensions For Android
  • Anko DSL Preview

其中Anko DSL Preview插件用于預(yù)覽使用DSL編寫的UI代碼,就像以前使用xml編寫UI文件時可以動態(tài)在“Preview”窗口預(yù)覽效果一樣。

上面三個插件下載安裝重啟之后,然后新建一個項(xiàng)目默認(rèn)配置Gradle如下:

    ext.kotlin_version = '1.1.0'
    ext.anko_version = '0.8.2'
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
    }
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

.........................

dependencies {
    .........................
    
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    compile "org.jetbrains.anko:anko-sdk15:$anko_version"
    compile "org.jetbrains.anko:anko-support-v4:$anko_version"
    .........................
}
repositories {
    mavenCentral()
}

這里添加了Kotlin對android的擴(kuò)展,同時也添加了Kotlin的gradle插件。我們打開系統(tǒng)默認(rèn)幫我們建的MainActivity,然后Code->Convert Java File to Kotlin File->OK,此時我們原有的Activity應(yīng)該將我們轉(zhuǎn)換成了如下內(nèi)容:

class KoTlinActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_ko_tlin)
    }
}

上面這一步是將java代碼轉(zhuǎn)換為Kotlin代碼。截止到現(xiàn)在,你什么都不用做,程序就已經(jīng)可以跑起來了。你可能要說代碼相比之下并沒有簡潔多少啊 ,當(dāng)然到這里并沒有結(jié)束,反而是開始,只是首先一起來體驗(yàn)下我們的第一個Kotlin代碼程序。

3、Kotlin完美給Java開發(fā)者打造

3.1 通用的集合框架和Kotlin的擴(kuò)展

通用的集合框架,ex如下:

  val list = arrayListOf(1, 2, 3, 4)
        list.add(5)
        list.remove(3)
        for (item in list) {
            debug(item);
        }

效果如下:

03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 1
03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 2
03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 4
03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 5

可以看到這里Kotlin寫法和java是差不多的。

至于Kotlin的擴(kuò)展,其實(shí)就是對java的庫進(jìn)行了進(jìn)一步擴(kuò)展,ex如下:

 val list = arrayListOf(1, 2, 3, 4, 5)
        list.forEach {
            debug(it)
        }
        debug("==========================")
        val doubleList = list.map {
            it * 2
        }
        doubleList.forEach {
            debug(it)
        }
        debug("==========================")
        val oddList = list.filter{
            it % 2 == 1
        }
        oddList.forEach {
            debug(it)
        }

打印如下:

03-09 16:18:06.978 28828-28828/com.Igeek.kotlin D/MainActivity: 1
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 2
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 3
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 4
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 5
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: ==========================
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 2
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 4
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 6
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 8
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 10
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: ==========================
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 1
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 3
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 5

3.1 Kotlin與Java的交互

Kotlin的標(biāo)準(zhǔn)庫更多的是對Java庫的擴(kuò)展,基于這個設(shè)計思路,你絲毫不需要擔(dān)心Kotlin對Java代碼的引用,你甚至可以在Kotlin當(dāng)中使用Java反射,反正只要是Java有的,Kotlin都有。最常見的就是Getter/Setter方法對應(yīng)到Kotlin屬性的調(diào)用,ex如下:
首先準(zhǔn)備一個java類:

8208E5B2-6AA0-4F0F-BA2D-A1F067D08DCC.png

調(diào)用如下:

       val javaPerson = Person()
        javaPerson.address = "Wo shi Kotlin"
        debug(javaPerson.address)

打印結(jié)果就是"Wo shi Kotlin"了,剛剛只顧著寫,忘了提一句,在Kotlin語法里面,是不用在后面加“;”的,有沒有感覺很爽,廢話不說了,可以看到我們調(diào)用時候,既沒有用到get方法也沒有用到set方法,是不是避免了總會有人說get/set方法影響性能的問題。
官網(wǎng)地址(有詳細(xì)的比較):https://kotlinlang.org/docs/reference/java-interop.html#static-methods-and-fields

4、簡潔 可靠 有趣

4.1數(shù)據(jù)類

在JavaBean中我們往往會覆寫諸如equals和hashcode等方法,一旦用到HashMap這樣的集合框架,總是出了問題都不知道找誰。Kotlin提供了一種非常簡單的方式來創(chuàng)建這樣的數(shù)據(jù)類,ex如下:

data class Main(val id:Int,val name:String)

//main方法調(diào)用
fun main(args:Array<out String>){
    println(Main(0,"Main函數(shù)"))
}

打印結(jié)果:

Main(id=0, name=Main函數(shù))

僅僅一行代碼,Kotlin就會創(chuàng)建出一個完整的數(shù)據(jù)類,并自動生成相應(yīng)的equals、hashcode、toString方法。

4.2 空安全與屬性代理

想想平時QA提的bug,不太靠譜的server,不太確定數(shù)據(jù)類型,均可能出現(xiàn)Exception,但我們總不能在所有地方都進(jìn)行判斷,第一次看到Kotlin的空安全處理,真的眼前一亮。
Kotlin的空安全設(shè)計,主要是在類型后面加?表示可空,否則就不能為null,ex如下:

val nullable: Int? = 0
val nonNullable: Int = 2
nullable.toFloat() // 編譯錯誤
nullable?.toFloat() // 如果null,什么都不做,否則調(diào)用toFloat
nullable!!.toFloat() // 強(qiáng)制轉(zhuǎn)換為非空對象,并調(diào)用toFloat;如果nullable為null,拋空指針異常
nonNullable.toFloat() // 正確

我們利用Convert Java File to Kotlin File生成的Kotlin代碼,在onCreate方法中也是如此考慮,savedInstanceState是否為空。

override fun onCreate(savedInstanceState: Bundle?) {}

注:這里的空指針異常是KotlinNullPointerException,而不是Java的NullPointerException。

5、Kotlin場景使用

好了,接下來我們就實(shí)戰(zhàn)說說Kotlin的用法,用如下代碼舉例:
java代碼:

8F167006-EA0F-4D14-BE9B-20BA6562DDEA.png

Kotlin代碼:

46EA6401-2A70-40FA-91A5-9EAA38E76670.png

5.1 場景一(控件findViewById)

findViewById有很多寫法,我們就從復(fù)雜到容易說起:

寫法一:

      private var tv_hello_view: TextView? = null
         .......................................
        tv_hello_view = findViewById(R.id.tv_hello_view) as TextView
        tv_hello_view!!.text = "Say Hello!!!"
        tv_hello_view!!.textSize = 22f
        tv_hello_view!!.setOnClickListener {}

有沒有發(fā)現(xiàn)寫法一還不如java寫法,貌似java寫法還簡單一點(diǎn),并且設(shè)置text和size時候,需要加兩個嘆號,不加的話貌似編譯器并不識別你是否為null,下面我們來看寫法二:

寫法二:

   private val  tv_hello_view: TextView by lazy{
        findViewById(R.id.tv_hello_view) as TextView
    }
   .......................................
        tv_hello_view.text = "Say Hello!!!"
        tv_hello_view.textSize = 22f
        tv_hello_view.setOnClickListener {}

這種寫法好像簡單了一點(diǎn),不過好像依然很復(fù)雜,注意在這里初始化的時候不要直接

private var tv_hello_view: TextView  //編譯錯誤

lazy是Kotlin的屬性代理的一個實(shí)例,它提供了延遲加載的機(jī)制。換句話說,這里的lazy提供了初始化aTextView的方法,不過真正初始化這個動作發(fā)生的時機(jī)卻是在aTextView第一次被使用時了。lazy默認(rèn)是線程安全的,你當(dāng)然也可以關(guān)掉這個配置,只需要加個參數(shù)LazyThreadSafetyMode.NONE即可:

private val tv_hello_view: TextView by lazy(LazyThreadSafetyMode.NONE){
     findViewById(R.id.tv_hello_view) as TextView
}

寫法三:

private lateinit var tv_hello_view: TextView
   .......................................
        tv_hello_view = findViewById(R.id.tv_hello_view) as TextView
        tv_hello_view.text = "Say Hello!!!"
        tv_hello_view.textSize = 22f
        tv_hello_view.setOnClickListener {}

這里主要用了lateinit 來修飾它,方法簡單了不少吧 ,但是findViewById這個單詞好長啊,能不能簡化啊,答案是肯定的,我們請出Anko,注意我們有依賴過dependencies喲。

寫法四:

private lateinit var tv_hello_view: TextView
   .......................................
        tv_hello_view = find(R.id.tv_hello_view) 
        tv_hello_view.text = "Say Hello!!!"
        tv_hello_view.textSize = 22f
        tv_hello_view.setOnClickListener {}

可以看到我們方法改成了find,并且沒了 as TextView,注意我們需要import org.jetbrains.anko.find。既然請出來了Anko ,那么我們還有終極方案,完全去除findViewById。

寫法五:

CD9648CF-79D0-48FB-AED7-59A2CAAF448B.png

可以發(fā)現(xiàn)直接操作tv_hello_view,這便是findViewById的終極寫法。
注:

1.導(dǎo)入了import kotlinx.android.synthetic.main.hello_layout.*包
2. tv_hello_view是hello_layout布局xml中的id

寫到這里,內(nèi)容也挺多了,我也只是把用法統(tǒng)一歸納一下,至于findViewById所牽扯出來的幾個點(diǎn):lazy,primitives, lateinit, Anko以及不要 findViewById仍然能找到控件的原理我并沒有去細(xì)致分析,后續(xù)有時間我會再補(bǔ)充上,當(dāng)然如果想更多的去了解,可以有一下資料參考:

Kotlin官網(wǎng)文檔地址:https://kotlinlang.org/docs/
《Kotlin for android Developers》中文翻譯: https://github.com/wangjiegulu/kotlin-for-android-developers-zh/blob/master/SUMMARY.md

在這里推薦一部Kotlin基礎(chǔ)學(xué)習(xí)視頻:https://pan.baidu.com/s/1b2tBH0 提取碼:nryk

本博客參考了一下文獻(xiàn):
Kotlin for android Developers》中文翻譯;
博客:http://www.println.net/post/Android-A-Powerful-Substitution-Kotlin
博客:http://mp.weixin.qq.com/s?__biz=MzIzMTYzOTYzNA==&mid=100000121&idx=1&sn=6a8c4b27dec4e03a58e888c5fa18b7e2&chksm=68a05e445fd7d752da50717bec037f51702aa9557b308114f2d7255109509bcd24c1a5d80903&mpshare=1&scene=23&srcid=0309PegdxPNifENVckrvhBZY#rd

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內(nèi)容