編輯:關於Android編程
Kotlin,原意是在俄羅斯的一個小島,JetBrain在2011年推出了以這個來命名的一個運行在JVM上的語言, 看上去有點類似C#和Scala的結合,並且同為靜態類型,作為一門JVM上的語言,可以輕松兼容Java,並且整個語言設計的非常輕量。目前的版本為0.12.200,尚未發布正式版。
Kotlin的下載和配置在其官網上有,在這裡就不再贅述了,值得一提的是,作為JetBrains家出品的語言,自家的IDEA當然全力支持!
Kotlin的語法非常簡潔,熟悉Java或者Scala的人都可以快速上手:
fun foo(va: Int): Int { return 1 }
也可以單行聲明:
fun foo(va: Int): Int = 1
lambda當然也是支持的:
var c = {foo: Int -> println(foo)}
Kotlin中的函數是一等對象,自然支持高階函數:
var c = {foo: Int -> println(foo)} fun fooTest(func: (Int)->()) = println("I'm Groot") fooTest(c)
類可以這樣進行聲明:
class Bar(var b: Int): Foo() { var c = 1 init { println("class initializer") } constructor(): this(1) { println("secondary constructor") } }
Bar類在這裡繼承了Foo類,Bar類有兩個構造函數,直接在Bar類頭的是primary constructor,另外一個構造函數使用constructor關鍵字定義,注意必須要先調用primary constructor,另外,init標明的是class initializer,每個構造函數都會首先調用class initializer裡面的代碼,再調用構造函數
class Outer { class Inner { } }
Kotlin同樣支持嵌套的內部類,不過和Java不一樣的是,Kotlin的內部類不會默認包含一個指向外部類對象的引用,也就是說,Kotlin中所有的內部類默認就是靜態的,這樣可以減少很多內存洩露的問題。另外,如果需要在內部類中引用外部類對象,可以在Inner類的聲明前加上inner關鍵字,然後在Inner類中使用標記的this:this@Outer來指向外部類對象
object Single { var c = 1 fun foo() = println("foo") }
Kotlin中使用object關鍵字聲明一個singleton對象,後面這裡的方法就可以直接使用Single.foo()來調用了
interface Interface { fun foo() { println(1) } fun bar() }
Kotlin中的interface,跟其他語言的trait非常像,而且也可以帶有默認的實現方法,並且不允許通過屬性來維護狀態。事實上,在上個版本中,interface的原來名稱是trait,而在M12現在這個版本中又改成了interface而已
在Kotlin中,嚴格區分了nullable和非nullable對象,甚至在編譯期解決了不少潛在的空指針問題:
我們先來看下普通的變量聲明
var c: String = "12123"
這裡聲明了一個String對象,其值為"12123",我們可以正常的使用這個對象的成員方法:c.length()
但是,如果在初始化的時候,變量c為空的話,這樣聲明就是錯誤的,會編譯不過:
var c: String = null
正確的聲明應該是這樣:
var c: String? = null
這裡在String後面加多了一個問號,表明這裡是一個Nullable的對象,說明這個變量在使用的過程中可能為空,而且,在調用這個變量的成員的時候,必須要使用這種語法:c?.length(),在調用的時候添加了一個問號,表明,如果c為空的時候,length()這個方法就不會調用。coffe-script也有類似的,這種語法糖減少了很多平時用到的Null-checked,簡化了代碼,而且從編譯器開始介入null-checked,大大減少了潛在的NullPointerException,而事實上,null的確也是一個billion dollar mistake
常年進行如此的調用語法常常會很惱人,因此在你進行顯式的Null-checked的時候,Kotlin的編譯器會認為後續的調用已經無需進行Null-checked,可以直接調用了:
if (c != null) { c.length() }
在Kotlin中,進行強制類型轉換可以使用as關鍵字,但有可能會拋出異常,因此,Kotlin引入了smart type cast:
if (c is String) { c.length() }
在上面的例子中,如果c是一個String對象,則在if塊中,可以直接使用String的方法,編譯器會智能的幫你識別出c在if-blcok裡面是一個String對象
Kotlin在一定程度上支持了一些FP的特性,包括強大的Pattern Matching,在Kotlin中可以使用when關鍵字:
var x = 3 when (x) { 1 -> print("x == 1") 2 -> print("x == 2") in 1..10 -> print("x is in the range") !in 10..20 -> print("x is outside the range") is Int -> println("is int") else -> { // Note the block print("x is neither 1 nor 2") } }
在Java中我們經常需要給系統的類添加一些實用的方法,但苦於不能直接擴展,於是就有了各種的xxxUtils類,導致代碼非常惡心,但是在Kotlin中,我們可以直接擴展庫裡面類的方法,通過function extension:
fun String.fucker() { println("a fucker") }
上面給String類添加了一個fucker方法,我們可以直接使用:
"123123".fucker()
這大大的減少了我們寫xxxUtils類的必要性
使用Kotlin開發Android app的配置非常簡單,按照官方給出的配置即可,直接在Gradle的配置文件build.gradle中添加一個依賴:
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
然後添加Kotlin插件的使用:
apply plugin: 'kotlin-android'
進行一次Gradle Sync之後,就可以直接在項目使用Kotlin編寫代碼了,另外,如果安裝了Intellij的Kotlin插件,可以選擇Tools->Kotlin->Configure Kotlin in Project,就可以自動進行上述的配置,一步到位
我寫了一個簡單的Demo app放到了Github上,有興趣可以看下使用Kotlin開發android app具體是怎樣的:Demo地址
dex有個65535方法數的限制,這對Android開發造成了很大的影響,在使用Kotlin進行android app開發的時候,需要將Kotlin的標准庫打包進入apk中,這意味著如果標准庫過大,對分包會造成很大的限制(因為這必須得打包在主dex中),所幸的是,Kotlin的哲學是“Java中有的,就盡量復用,不再自行創造一套”,使得整個Kotlin的標准庫非常小,我們可以簡單將Kotlin的標准庫和其他比較常用庫進行一下對比:
包名 android-support-v13.jar android-support-v4.jar android-support-v7-appcompat.jar guava-18.0.jar scala-library-2.12.0-M1.jar kotlin-stdlib-0.12.213.jar 方法數 8219 8118 4624 14833 51248 7228
可以看出來Kotlin的標准庫相當小,只有7000多個方法,比support-v13和support-v4還小,這體現了Kotlin的設計哲學之一:"100% interoperable with Java",基本上Java已經有的,Kotlin會盡量復用。而對比來看,同樣是JVM上的語言,我們也可以選擇使用Scala來進行Android開發,但Scala標准庫有5萬多個方法,全部打包進主dex中,很容易就導致app爆主dex了。所以綜合來看,輕量形的Kotlin還是相當適合進行Android開發的。
Anko是JetBrains推出的一個簡化Android開發的庫,同樣由Kotlin來編寫,主要的革命在於,聲明UI的方式,完全拋棄了xml的使用,使用Anko,聲明UI是這樣做的:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val customStyle = { v: Any -> when (v) { is Button -> v.textSize = 26f is EditText -> v.textSize = 24f } } verticalLayout { padding = dip(34) imageView(android.R.drawable.ic_menu_manage).layoutParams { margin = dip(16) gravity = Gravity.CENTER } val name = editText { hintResource = R.string.name } val password = editText { hintResource = R.string.password inputType = TYPE_CLASS_TEXT or TYPE_TEXT_VARIATION_PASSWORD } button("Log in") { onClick { tryLogin(name.text, password.text) } } }.style(customStyle) }
你沒看錯,的確是在Activity類的onCreate方法中直接聲明UI的布局。
Anko看起來像是使用了一種類似DSL的方式聲明了界面的UI,這裡主要是使用了Kotlin的其中兩個特性:
因此這裡聲明布局的方式,其實全是Kotlin的原生代碼,鵝妹子嘤!這樣做有顯然的好處:
從前幾章我們分別學習了屬性文件存儲輸數據,內儲存存儲數據,和外部儲存存儲數據,今天我們來學習一下android 輕量級數據庫Sqlite數據庫的數據存儲 首先必須了解
這次要介紹一下對象池模式(Object Pool Pattern),這個模式為常見 23 種設計模式之外的設計模式,介紹的初衷主要是在平時的 android 開發中經常會
首先,我們看一下什麼是serializer,serializer就是串行化,又名序列化。它可並不只是簡單的把對象保存在存儲器上,它可以使我們在流中傳輸對象,使對象變的可以
1、BitmapFactory解析Bitmap的原理BitmapFactory提供的解析Bitmap的靜態工廠方法有以下五種:Bitmap decodeFile(...)