阿里P6P7【安卓】進階資料分享+加薪跳槽必備面試題
目前公司的項目已經全面使用Kotlin,轉換的過程的確不是怎麼讓人溫馨,可是讓人欣慰的是結局是讓人滿意的。Kotlin的確可讓代碼簡潔,安全而且高效。這裏分享一下,在使用Kotlin中那些讓人以爲溫馨的地方。面試
未完待續..安全
開發中不免須要根據多個字段去拼接一條字符串作展現,在過長或者過於複雜的數據邏輯的時候,用Java實現起來都過於冗長。Kotlin 使用 $ 放在變量名的前面去表達字符串中的變量和表達式,從而簡化了這一過程。網絡
val str = "hello" // str length : 5 print("$str length: ${str.length}")
在使用Java開發Android的過程當中,避免不了大量的空安全斷定代碼,介於Kotlin要很好的兼容Java,在這個問題上Kotlin設計一整套新的類型系統(這裏不做研究)來完善優化它。架構
全部的類型都分爲可空和不可空類型,而且針對不可空類型強制要求初始化,在一開始就讓開發者高標準的、嚴謹的使用變量,是一種規範性的要求。可是可空類型可能會在程序中更普遍的應用,針對這一點,Kotlin也有Elvis 操做符來進行安全訪問或者避免空值狀況,見簡潔代碼。app
// 不可空類型(使用前必須初始化) var notCanNullInt: Int = 0 // 可空類型 var canNullInt: Int? = null // 安全訪問 print("${canNullInt?.toShort()}") // 避免空值 爲空給與一個默認值 val age = canNullInt ?: 18 // 爲空返回 val time = canNullInt ?: return
這一點能夠說是對不可空類型的更進一步優化,開發中總有一些變量是在某些時機纔會被初始化,而不是類加載的時候就加載。延遲加載是很好的東西,能夠省去初始化的成本,在變量真正被須要的時候才被初始化。框架
val userInfo: UserInfo by lazy { UserInfo() } lateinit var person: InvationPerson
Kotlin有區間的概念,這個概念讓建立循環更加易讀方便。函數
// print :0 1 2 3 4 5 6 7 8 9 10 for (i in 0..10) { print("$i ") } // print :10 9 8 7 6 5 4 3 2 1 0 for (i in 10 downTo 0) { print("$i ") } // print :0 2 4 6 8 10 for (i in 0..10 step 2) { print("$i ") } // print :0 1 2 3 4 5 6 7 8 9 for (i in 0 until 10) { print("$i ") } val map = mapOf("a" to 1, "b" to 2) // print :a - 1 b - 2 for ((key, value) in map) { print("$key - $value") }
遍歷集合是基操,對於一些稍微複雜一點的數據邏輯,Java實現起來並不友好。工具
固然後面有了RxJava來進行補救,不過Kotlin作的彷佛要更好一點。(這裏就不討論Kotlin的集合框架架構了)組件化
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9) list.forEach { print(it) } // 映射 val listUp = list.map { it + 2 } // 過濾 val listFilter = list.filter { it % 2 == 0 } // asSequence 懶處理 map filter中都存在遍歷操做 asSequence能夠將它們合併起來 只存在一次遍歷 提高性能 val listMore = list.asSequence().map { it + 2 }.filter { it % 2 == 0 }.toList()
asSequence 對提高效率大有裨益,其餘的操做就不一一列舉了性能
重載是很比較常見的操做,可是有時候這種方式會出現不少相同的模板代碼。Kotlin的默認參數,能夠給參數指定默認值,而且在調用的時候像給變量賦值同樣給參數賦值而不用像Java同樣非要按照順序去傳值。
而且由於具備默認值的緣由,因此調用的時候能夠根據具體狀況傳遞參數,更加靈活、更加易讀和簡潔。
class Point(val x: Float = 0F, val y: Float = 0F) val x = Point(x = 10F)// x 10 y 0 val y = Point(y = 10F)// x 0 y 10 val xy = Point(x = 10F, y = 10F)// x10 y10
開發中Bean文件是必不可少的,可是Java的Bean文件大部分都是模版代碼,雖然有插件自動生成,可是依然會以爲比較繁瑣,Kotlin能夠將這些類申明爲Data類,這些類會默認實現equals(),hashCode(),toString() 和copy() 方法,從幾十行Java代碼簡潔到幾行代碼,Kotlin只用聲明 一個data class
data class Person( val name: String, val age: Int, val sex: Int ){ //.... }
這是Kotlin提供的函數庫,使用後會簡化很多的樣板代碼。稍微不同的地方是它們的this和it各自指向不同,以及返回值得不同,使用得時候根據具體得狀況來就能夠了.
run
val str = "a" val res = str.run{ // this 指向 "a" it沒有指向 // 能夠直接訪問對象得屬性 print(length) 1 // 最後一行返回值爲1 }
let
val str = "a" val res = str.let{ // this 指向當前class // it 指向a print(it.length) "let" // 返回值"let" }
with
val res = with(user){ // this 指向user it無指向 println(age) println(name) "with" // 返回值 }
apply
val str = "a" val res = str.apply{ // this指向str it 無指向 a // 返回值 }
對於Java的Stwich再熟悉不過,可是它使用起來有比較多的限制,有時候面對複雜的邏輯會顯得乏力。
Kotlin的when表達式能夠匹配幾乎任何東西(字面值,枚舉,數字,範圍,類型,表達式,甚至函數(kotlin函數至上))簡單感覺下:
fun whenTest(number: Number?): String { return when (number) { null, 0 -> "empty" 1 -> "tiny" in 2..5 -> "small" is Long -> "big number" else -> "unKnow" } }
固然有時候使用when會有一些比較麻煩的事情,好比對else狀況的處理,由於你的程序中明明只有這麼幾種狀況,可是你卻不得不寫上關於else的狀況處理,這樣的代碼讓人以爲不安心,也下降了可讀性,這個時候能夠結合Koltin的密封類來處理,好比對網絡狀況的回執,對錯誤的處理,Android對RecyclerView的適配中多中ViewHolder的處理
// 密封類的存在讓整個過程當中可能出現的狀況更加嚴謹 sealed class NetWorkResult data class Success(val resJson: String) : NetWorkResult() data class Failure(val error: Error) : NetWorkResult() // 代碼更加易讀 fun netWorkTest(result: NetWorkResult) { when (result) { is Success -> { showResult(result.resJson) } is Failure -> { showError(result.error) } } }
擴展多是最受歡迎的一個特性,由於它可讓你少寫不少工具類,而且讓代碼看起來更易讀,更簡潔。好比作一個防止重複點擊的操做。
// 擴展點擊事件屬性(重複點擊時長) var <T : View> T.lastClickTime: Long set(value) = setTag(1766613352, value) get() = getTag(1766613352) as? Long ?: 0 // 重複點擊事件綁定 inline fun <T : View> T.singleClick(time: Long = 800, crossinline block: (T) -> Unit) { setOnClickListener { val currentTimeMillis = System.currentTimeMillis() if (currentTimeMillis - lastClickTime > time || this is Checkable) { lastClickTime = currentTimeMillis block(this) } } }
一開始我並無注意到這個特性,由於項目是組件化開發,在跳轉傳值上都採用了ARouter,可是當我發現Kotlin對這個作的改造的時候仍是很是開心~
// 建立Bundle 和建立map 同樣優雅 val bundle = bundleOf( "KEY_ONE" to 1, "KEY_TWO" to 2L, "KEY_THREE" to true ) // 不再用寫繁瑣的Parcelable實現 @Parcelize data class Person(val name:String):Parcelable