写在前面:《Kotlin For Android》这本书走马观花看了两遍,感觉效果不好,重读一遍,梳理一下知识点,带你快速熟悉Kotlin。
建议每个知识点先看完再思考细节问题,并且细节问题,我会列出提示大家。
1. Kotlin的优点
①更易表达
使用data class 定义model,天生可以直接访问属性,天生自带toString()等方法。
data class Artist( var id: Long, var name: String, var url: String, var mbid: String)
②空安全
使用Kotlin可以表示一个引用所指的对象可以为空。
var notNullArtist: Artist = null //这样不可以
var artist: Artist? = null //这样可行,Artist可以为null
artist.print() //这样不可行,Artist可以为null
artist?.print() //这样可行,可空类型必须带上?
artist!!.print() //这样可行,当我们确定artist不为空的时候才能这样使用,否则抛出异常
val name = artist?.name ?: "empty" //使用?:符号给一个Null对象一个初始值
③可以给任意Class扩展方法
这样一个用处是可以省略一个工具类,代替做法是直接给某个类扩展一个方法就行了。并且这个方法是可以直接写在一个.kt文件中,不依赖于任何类。例如,给Fragment扩展一个toast方法:
fun Fragment.toast(message: String, duration: Int = Toast.LENGTH_SHORT) = Toast.makeText(getActivity(), message, duration).show()
调用方法:fragment.toast("Hello World") 或者 fragment.toast(message = "Hello", duration = Toast.LENGTH_SHORT);
④支持函数式编程--Lambda
用法和JAVA8 支持的Lambda语法一致
view.setOnClickListener { toast("Hello world!')}
TIPS:
①Kotlin没有基本数据类型,只有它们对应的包装类型。Double、Float、Long、Int、Short、Char、Byte、Boolean
②一句语句独占一行时,“;”可带可不带
③定义变量的方式:var name: String = "LD" //var表示变量,也可用val表示常量。name为变量名。String为变量类型,此处亦可以省略,因为可以根据“LD”进行隐式转换判断类型为String。
④方法天生是拥有若干个参数个数不同的重载方法。可以指明如果不传入的默认值,也可以不指明。例如知识点②给一个Toast默认时间。
⑤当方法体只有一句话时,可以省略“{}”,使用“=”连接方法体
2.如何声明类和函数
先上代码:
class Person(name: String, surname: String){
init{}
constructor(name: String){}
fun run(){}
}
每一个Class都有一个默认的构造函数,在声明Class的同时定义构造函数,构造函数的函数体在init{}中定义。同时你可以使用construct关键字定义构造函数的重载方法。
每一个Class默认是Any(类似Java中的Object)的子类,同时你可以继承一个其他类,单继承这一点跟Java中一样。
每一个Class默认是Closed的,默认不能够被其他类所继承,除非使用open/abstract关键字声明。题外话,建议少使用继承模式,可以使用组合扩展方式进行编码,举个栗子:class Student(val person: Person)。
声明方法的方式:fun 方法名(){ // 方法体 }
TIPS:
①在String中我们可以使用模板,例如:toast.makeText("$message", Toast.LENGTH_SHORT),如果你的message比较复杂,可以使用toast.makeText("${user.name}", Toast.LENGTH_SHORT),记得带“{}”哦。
②创建一个对象不需要“new”这个关键字,例如:val person = Person("LD")
3.变量和资源文件
①基本类型:Int、Double、Char等。Int不能够隐式转换成Double,Char不能够直接作为数字,使用“and”或“or”代替“&”或“|”。
val i:Int = 7; val d: Double = i.toDouble();
val c:Char = 'c'; val i: Int = c.toInt();
val bitwiseOr = FLAG1 or FLAG2; val bitwiseAnd = FLAG1 and FLAG2;
②String可以被当成Array。
val s = "Example"
val chars = s[2]
for (c in s){ print(c); }
4.数据类(Java Beans)
data class Forecast(val date: Date, val temperature: Float, val details: String)
①自带扩展方法:equals、hashCode、copy
②复制一个数据类:val f1 = Forecast(Date(), 27.5f, "shiny day"); val f2 = f1.copy(temperature = 30f); //在复制的同时,改变温度值。此时不指向同一个对象。
③将object的值传递给变量:val f1 = Forecast(Date(), 27.5f, "shiny day"); val (date, temperature, details) = f1
以上代码相当于:val date = f1.component1(); val temperature = f1.component2(); val details = f1.component3(); //在这个实现后面的逻辑非常强大,比如在一个迭代器中可以使用Map的Key和Value: for( (key, value) in map) { Log.d("map", "key:$key, value:$value") }
5.解析数据
①当我们将json转成数据类时,类名必须和json中的名字一致,或者可以给数据类起个Serialised Name.
②在Kotlin中不存在静态变量、静态常量、静态方法。但是我们可以使用companion object来达到static的效果,类所有的实例可以共享它们。
public class ForecastRequest(val zipcode: String){
companion object{
private val URL = "http://api.openweathermap.org/..."
}
public fun execute(): ForecastResult {
val forecastJsonStr = URL(URL + zipcode).readText()
return Gson().fromJson(forecastJsonStr, ForecastResult::class.java)
}
}
说明:URL().readText()进行网络请求,并返回结果。 “ForecastResult::class.java”相当于Java中的“ForecastResult.class”。
③在界面上展示数据
public class ForecastListAdapter(val weekForecast: ForecastList) :
RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
ViewHolder? {
return ViewHolder(TextView(parent.getContext()))
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
with(weekForecast.dailyForecast[position]) {
holder.textView.text = "$date - $description - $high/$low"
}
}
override fun getItemCount(): Int = weekForecast.dailyForecast.size()
class ViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)
}
with源码:
/**
* Calls the specified function [f] with the given [receiver] as its receiver and returns its result.
*/
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
注意:with操作符是kotlin库中一个重要的成员,你查看源码发现,with的作用是,将第二个参数作为第一个参数的扩展方法。这个操作符非常有用,我们以后会经常用到。