阿里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