来自《第一行代码》
基础
控制语句
Kotlin 的 if 可以有返回值,就是花括号里头最后一行代码。
when 比 switch 更高级。也能有返回值。如果不写小括号和里头的东西,就可以在条件的地方写上 someParam == 1
这种东西。不必使用 equals。
1 | fun qwq(name: String) = when (name) { |
for-i 循环没了(震撼我妈,用:
1 | for (i in 0..10) { |
两个点是闭区间。until 是左闭右开区间。在后头加上 step 2
可以设置步长。for (i in 10 downTo 1)
倒序。
对象
定义类就:
1 | class Person { |
直接点运算符访问、修改对象和执行函数。注意,类默认不可继承。要继承的话父类 class 前头加 open,子类用 class Student : Person() {...
这种东西。
构造函数分为主构造函数和次构造函数。主构造函数可以写参数
1 | open class Person(val name: String, var age: Int) { |
加了 val/var 以后的参数自动成为本类的字段。所以说 Student 可以改造为 class Student(val school: String, name: String, age: Int) : Person(name, age) {...
这种东西,不加 val/var 就能把作用域限定在主构造函数里头。
顺带一提每个类都可以写个 init{ ... }
执行一些代码。所有次构造函数都必须调用主构造函数。例如 Person 写一个 constructor() : this("", 0) {}
。可以没有主构造函数。
修饰符就是把 java 四种修饰符的 default 变成了 internal。public 变成了什么都不写的默认项目(java 是 default),internal 是同一模块可见。protected 去掉了同一包路径可见。
数据类就像 java bean,前面加个 data 就行了,equals 什么的都不用写了……没有代码的话花括号都不用了(喜
单例类直接把 class 换成 object 完事(tql
1 | data class CellPhone(val brand: String, val price: Double) |
接口
没有 extends 和 implements 了,直接冒号后头跟上继承的类和实现的接口。逗号隔开。@Override
变成了扎起 fun 前头加 override
。接口也可以有默认的实现函数。
Lambda
listOf(a, b, c) 创建不可变集合,mutableListOf 创建可变的(当然也可以一个一个 add)。
lambda 表达式:{param1: Type, xxx -> 函数体}
。
函数式 api:
1 | val list = listOf("apple", "banana", "billy") |
lambda 表达式是函数最后一个参数可以把 lambda 表达式移到外头,小括号也可以省略,一个参数也可以直接用 it 表示。所以上面的可以写成 list.maxBy {it.length}
和 js 一样,也有 filter 和 map。用 any 和 all 做判断。这东西自行百度吧。来一段省略带师:
1 | Thread(object: Runnable {// java 的 new 变成了 object |
对一个对象使用 let 可将调用对象传递到 lambda里头,例子看下头。
空指针
kotlin 把空指针异常消灭在编译期。Int
不为空,Int?
表示可以为空。敢写第二种就要判空了。
例如一个 student: Student?
,直接 student.study()
是不行的。要么包一个 if 判 null,要么就用 student?.study()
,非空才执行。用 a ?: b
表示 a 非空的时候为 a,a 为空则为 b。
1 | student?.let {stu -> |
字符串可以内嵌表达式,比如
1 | val a = 1 |
可以用 lateinit 告诉编译器某个变量是延迟初始化的。
一些标准函数
with 接收一个对象和一个 lambda 表达式,在表达式中提供那个对象的上下文并以最后一行语句为返回值。
1 | fun main() { |
run 差不多,不过是要 obj.run {xxx},不能直接用。
apply 和 run 差不多,但是没有返回值而是返回对象本身。
静态方法
kotlin 弱化了静态方法的概念,要么用单例类,要么套一个 companion object。(其实调用的就是这个伴生类的方法)。真正的静态方法加 @JvmStatic 或者是顶层方法。
高阶函数
在参数列表里里头写 func: (String, Int) -> Unit
,表示接受一个以 String 和 Int 为参数并什么也不返回(Unit 类比 void)的函数(lambda)。引用一个函数可以使用 ::funcName
。
输入输出
对一个 writer 使用 use,例如 writer.use { xxx }
,会在 lambda 执行完毕以后关闭外面的流。
Activity
可以使用 Intent 来调起别的 activity。可以通过指定一个 action 多个 category(不一定都要有)来让系统找出合适的 activity 启动(隐式的),也可以直接钦点 activity(显式的)。自己的 activity 在 AndroidManifest.xml 里头对应的 activity 标签下写 intent-filter,用处看名字就能猜出来。
比如:
1 | button1.setOnClickListener { |
可以自己在 intent-filter 标签里头写上 data 标签响应 https 协议,之类的操作。(感觉这就是实现用别的应用打开的方式啊2333
intent 还能携带额外的 data。也可以用 startActivityForResult 来调用一个 activity 让它返回数据。
生命周期
使用任务栈来管理 activity。activity 有运行、暂停、停止、销毁状态。
启动模式
standard,singleTop(栈顶是当前 activity 就不会再创建一个了),singleTask(返回栈里就一个),singleInstance(存放在单独的返回栈)
类委托
使用 by 关键字。
BroadcastReceiver
属于四大组件。就像 activity 一样,继承 BroadcastReceiver 并重写 onReceive 方法即可。动态注册也一定要取消注册。
intent setPackage 以后变成显式广播,静态注册的 BroadcastReceiver 可以收到,然后 sendBroadcast。
有序广播可以截断,同步执行,标准广播不行。有序广播用 sendOrderBroadcast,在 AndroidManifest 中设置优先级,在 onReceive 中用 abortBroadcast 截断。
持久化
存文件,SharedPreferences 存储键值对,数据库。
1 | class MainActivity : AppCompatActivity() { |