这个是一些学习笔记。碎碎记。
kotlin与android,现在是kotlin通过插件编译成jvm能运行的机器码,java有的东西kotlin都有。
kotlin支持方法拓展,但是不能写到类里边。写到类里边无效。这个特性非常重要,为拓展提供了新思路。
方法拓展还可以给已有方法重命名,当然,原来方法名还能用,就是包了一层。
fun 类名.拓展方法(args){} //子类可以继承
public var TextView.text: CharSequence // 拓展 重命名
get() = getText()
set(v) = setText(v)
支持lambda,我感觉相当于匿名内部类。
好像要在Javabean的对象前加data
支持对象copy并修改值。
类继承,所有类继承自Any,(不是Object了),默认类不可继承,只有open 或abstract 修饰的类才可以。
函数可以简写了,直接在返回值类型后加=
构造方法和初始化用constructor和init,constructor可以重载
类型转换用as ,安全转换用as?,不成功就是null
静态:
- 静态类前边加object;
- 一部分是静态方法的情况 : 将方法用 companion object { } 包裹即可,这个叫“伴生对象”,可以给伴生对象起名字,放到object后,也可不加。
bean类不用写getter、setter了, 其实还有,只是不用写,可以重写。
public classs Person {
var name: String = ""
get() = field.toUpperCase()
set(value){
field = "Name: $value"
}
}
重写用override,加到fun前面
是空安全的,支持?:操作符,和Java里的意思不一样,java里的那个三目运算符只能用if、else表示,但是可以简写
hah?.print() //hah不为空才打印
hah!!/print() //强制打印,可能会有exception
hah?.name?:"null" // null打印null,代替值
//在变量类型后面加上问号,代表该变量是可空变量 可空变量需要强制判null
var name: String? = "zhangsan"
var lenght:Int = if(haha!=null) haha.length: -1 // 原来java的三目这么用了
with函数,直接使用with括号对象的属性方法。
kotlin强制指定泛型,不加报错
var list = ArrayList<String>()
集合里边有好多拓展方法,map mapto,groupBy,filter很多,详见
kotlin-stdlib-1.1.51-sources.jar!/generated/_Collections.kt
有个库叫anko,这是一个对Android使用kotlin的拓展库,JetBrains开发的。提供了新方式写UI布局。
记一个简化过程
简化 setOnClickListener()
我们用 Android 中非常典型的例子去解释它是怎么工作的:View.setOnClickListener()方法。如果我 们想用 Java 的方式去增加点击事件的回调,我首先要编写一个 OnClickListener 接口:
然后我们要编写一个匿名内部类去实现这个接口:
public interface OnClickListener {
void onClick(View v);
}
view.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
}
})
我们将把上面的代码转换成 Kotlin(使用了 Anko 的 toast 函数):
view.setOnClickListener(object : OnClickListener {
override fun onClick(v: View) {
toast("Click")
}
}
很幸运的是,Kotlin 允许 Java 库的一些优化,Interface 中包含单个函数可以被替代为一个函数。 如果我们这么去定义了,它会正常执行:
fun setOnClickListener(listener: (View) -> Unit)
一个 lambda 表达式通过参数的形式被定义在箭头的左边(被圆括号包围),然后在箭头的右边返
回结果值。在这个例子中,我们接收一个 View,然后返回一个 Unit(没有东西)。所以根据这种思
想,我们可以把前面的代码简化成这样:
view.setOnClickListener({ view -> toast("Click")})
这是非常棒的简化!当我们定义了一个方法,我们必须使用大括号包围,然后在箭头的左边指定参数, 在箭头的右边返回函数执行的结果。如果左边的参数没有使用到,我们甚至可以省略左边的参数:
view.setOnClickListener({ toast("Click") })
如果这个函数的最后一个参数是一个函数,我们可以把这个函数移动到圆括号外面:
view.setOnClickListener() { toast("Click") }
并且,最后,如果这个函数只有一个参数,我们可以省略这个圆括号:
view.setOnClickListener { toast("Click") }
比原始的 Java 代码简短了 5 倍多,并且更加容易理解它所做的事情。非常让人影响深刻。
inline 内联函数, Anko也是基于这个思想来实现的 Android layout 的 DSL 化。
inline fun testInline(code: () -> Unit) {
code();
}
testInline {
print("af")
}
委托,标准委托,用by
lazy 懒加载,就是使用的时候才进行调用,一般用于初始化
val datebase: SQLiteOpenHelper by lazy {
MyDatabaseHelper(applicationContext)
}
observable 观察者
var property by Delegates.observable(""){
d,old,new -> // 这个是一个lambda表达式 实际是onchange 源码在下边几行
database.saveChanges(this,new)
}
// 源码
public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
}
// 也可以这么写
var property by Delegates.observable("", onChange = {
property: KProperty<*>, oldValue: String, newValue: String ->
database.saveChanges(oldValue, newValue)
})
Vetoable 否决器(姑且这么叫吧)用于决定一个值是不是可以赋给变量
//只能是"HAHA"
var onlyHAHA by Delegates.vetoable("", { p, old, new ->
new == "HAHA"
})
Not Null 指定变量不能为空,为null则抛出异常
var notNull: String by Delegates.notNull()
从Map中获取映射值;map以构造方法的方式传入bean,bean中属性后添加by map,即可自动匹配,if field_name==map.key then:field_value=map.value
自定义一个委托,实现一个值只能修改一次
// 定义
private class NotNullSingleValueVar<T>() : ReadWriteProperty<Any?, T> {
private var value: T? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value ?: throw IllegalStateException("not initialized")
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = if (this.value == null) value else throw IllegalStateException("already initialized")
}
}
//封装
object DelegatesExt {
fun <T> notNullSingleValue():
ReadWriteProperty<Any?, T> {
return NotNullSingleValueVar()
}
}
// demo
var notNullSingle: String by DelegatesExt.notNullSingleValue()
object关键字;在参数中,相当于new一个匿名内部类;修饰类,相当于单例模式
view.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
}
})
// 我们将把上面的代码转换成 Kotlin(使用了 Anko 的 toast 函数):
view.setOnClickListener(object : OnClickListener {
override fun onClick(v: View) {
toast("Click")
}
}
// 简单单例模式
object Obj{
init{
println("object init...")
}
}
泛型函数
不仅类可以有类型参数。函数也可以有。类型参数要放在函数名称之前:
fun <T> singletonList(item: T): List<T> {
// ……
}
fun <T> T.basicToString() : String { // 扩展函数
// ……
}
//要调用泛型函数,在调用处函数名之后指定类型参数即可:
val l = singletonList<Int>(1)
还有好多不容易理解的特性,以后继续更新。
放个图,哈哈
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!