2.Kotlin重要关键字

object

生成静态内部类

class DemoManager{
    object MyObject {
        fun a() {
            Log.e(TAG,"此时 object 表示 直接声明类")
        }
    }
}

如果需要调用 a()方法:

//kotlin中调用
fun init() {
    MyObject.a()
}
//java中调用
 MyObject.INSTANCE.a();

生成匿名内部类对象

val textView = findViewById<TextView>(R.id.tv)
textView.setOnClickListener(object : OnClickListener {
        override fun onClick(p0: View?) {
            Toast.makeText(this@TestActivity, "点击事件生效", Toast.LENGTH_LONG)
        }

})

生成单例对象

object DemoManager {
    private val TAG = "DemoManager"
        
    fun a() {
        Log.e(TAG,"此时 object 表示 声明静态内部类")
    }
    
}

companion : 伴生对象

注意看[1.Kotlin基础概念]对该部分的解释

  • companion object {}中用来修饰 静态常量,或者静态方法,单例等等
  • companion object 修饰为伴生对象,这个对象被这个类的所有对象所共享且只能存在一个,但并不是静态属性或方法,只是创建Companion静态对象来调用里面的属性和方法
  • companion object 中调用不到外部成员变量,如同java中的静态方法无法调用非静态的成员变量,想调用则将所引用的成员变量也修饰静态的

incline 内联函数

  • 一个函数有lambda表达式作为形参的时候就可以用incline关键字修饰
  • 当一个函数被声明为inline时,它的函数体是内联的,也就是说,函数体会被直接替换到函数被调用地方
inline fun inlineFunc(prefix : String, action : () -> Unit) {
    println("call before $prefix")
    action()
    println("call after $prefix")
}

fun main(args: Array<String>) {
    inlineFunc("inlineFunc") {
        println("HaHa")
    }
}
运行结果为:

>> call before inlineFunc
>> HaHa
>> call after inlineFunc
//最终它会被编译成下面的字节码:
//函数体会被直接替换到函数被调用地方
fun main(args: Array<String>) {
    println("call before inlineFunc")
    println("HaHa")
    println("call after inlineFunc")
}

By

  • 将属性访问器的实现委托给另一个对象

接口代理

代理接口中的函数
//kotlin代理 编译后实为java中的静态代理
interface Animal{
    fun bark()
}

class Dog : Animal {
    override fun bark() {
        println("DOG's Bark()")
    }
}

class Zoo(animal: Animal) : Animal by animal {
    override fun bark() {
        println("ZOO’s Bark")
    }
}

fun main(args: Array<String>) {
    Zoo(Dog()).bark()
}

代理接口中的属性
  • 将接口的实现委托给另一个类实现
  • 从使用上来说,对接口形参不仅要使用还要对该接口形参进行修改就可以用这种方式
interface Base {
    val message: String
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override val message = "BaseImpl: x = $x"
    override fun print() { println(message) }
}

class Derived(b: Base) : Base by b {
    // 在 b 的 `print` 实现中不会访问到这个属性
    override val message = "Message of Derived"
  //但是在复写了print方法后,执行的依然是Derived的print方法调用的本类中的成员变量
//    override fun print() {
//        println(message)
//    }
}

fun main() {
    val b = BaseImpl(10)
    val derived = Derived(b)
    derived.print()
    println(derived.message)
}

注意: 在代理接口中,假如当前类没有复写被代理类中的接口或者变量,在执行时将执行原来的类中的逻辑,假如复写,则执行复写后的

属性代理

  • 将属性的实现委托给另一个对象
class Example {
    var p: String by Delegate()
}
class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }
 
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}
fun main(args: Array<String>) {
    val e = Example()
    println(e.p)
}

输出:Example@33a17727, thank you for delegating ‘p’ to me!

当我们给p赋值的时候,setValue会被调用

e.p = "NEW"

输出:NEW has been assigned to ‘p’ in Example@33a17727.


lateinit

val name: String by lazy {
    "Rocker"
}

lateinit var name:String;
fun testName(){
  name = "Rocker"
}
两者区别:
by lazy  修饰val的变量
lateinit 修饰var的变量,且变量是非空的类型

lazy

  • 实现懒加载,变量第一次被使用时才进行初始化
  • 注意只允许val常量进行懒加载,var变量不可以
  • 初始化lazyValue的过程默认是线程安全的,通过synchronized锁来保证

lazy函数:

public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

lazy方法返回一个Lazy对象,入参是一个lambda

成员变量的懒加载
val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}

fun main(args: Array<String>) {
    println(lazyValue)
    println(lazyValue)
}
//输出:

computed!
Hello
Hello

当第一次获取lazyValue的值时,会先初始化lazyValue,然后把值保存起来,下一次获取lazyValue时直接获取保存好的值即可

局部变量的懒加载

在java中函数的形参只能是接口类型,不能是接口中的方法类型,但在Kotlin中,方法形参的类型可以是接口中的方法:

        fun example(mRun: () -> Runnable) {
        //对一个局部变量进行懒加载赋值
        val lazyValue: String by lazy {
            println("computed!")
            "Hello"
        }
        //局部变量还可以是接口中的一个方法
        val lazyValue2 by lazy(mRun)
        lazyValue2.run()
    }


lazy 取消同步锁
  • 当lazyValue的初始化不会涉及到多线程,可以传入LazyThreadSafetyMode.NONE来取消同步锁
val lazyValue: String by lazy(LazyThreadSafetyMode.NONE) {
    println("computed!")
    "Hello"
}

LazyThreadSafetyMode:

  • SYNCHRONIZED(默认模式,是安全模式)
  • NONE(非安全模式)
  • PUBLICATION : 使用了AtomicReferenceFieldUpdater(原子操作)允许多个线程同时调用初始化流程

监听赋值

observable(赋值后)
  • 变量被赋值时会发出通知
  • val常量和var变量均可使用
import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("<no name>") {
        prop, old, new ->
        println("$old -> $new")
    }
}

fun main(args: Array<String>) {
    val user = User()
    user.name = "first"
    user.name = "second"
}
输出:

<no name> -> first
first -> second
vetoable(赋值前)
  • true表示同意修改,false表示禁止修改,该回调会在属性值修改前调用
import kotlin.properties.Delegates

class User {
    var name: String by Delegates.vetoable("<no name>") { p, oldValue, newValue ->
        if (newValue == "first"){
            return@vetoable true // 返回true表示first可以赋值给name
        }
        return@vetoable false // 返回false表示拦截其他赋值操作。
    }
}

fun main(args: Array<String>) {
    val user = User()
    user.name = "first"
    println(user.name)
    user.name = "two"
    println(user.name)
}
输出:

first
first

by map

  • 把map中某个key值映射为变量
  • 当映射的变量值被修改后,map中的值也会被修改
fun main(args: Array<String>) {
    val map = mutableMapOf("name" to "小明", "age" to 1)
    var name: String by map
    println(name)
    name = "小红"
    println(map["name"])
}
输出:

小明
小红

提供代理

  • 可以干预代理类的创建过程。提供provideDelegate方法即可,该方法返回要创建的代理对象
class MyUI {
    fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { ... }

    val image by bindResource(ResourceID.image_id)
    val text by bindResource(ResourceID.text_id)
}
class ResourceDelegate<T> : ReadOnlyProperty<MyUI, T> {
    override fun getValue(thisRef: MyUI, property: KProperty<*>): T { ... }
}
    
class ResourceLoader<T>(id: ResourceID<T>) {
    operator fun provideDelegate(
            thisRef: MyUI,
            prop: KProperty<*>
    ): ReadOnlyProperty<MyUI, T> {
        checkProperty(thisRef, prop.name)
        // create delegate
        return ResourceDelegate()
    }

    private fun checkProperty(thisRef: MyUI, name: String) { ... }
}
  • provideDelegate方法有两个参数,参数1是代理属性所在的类,即image所在的类:MyUI。参数2是代理属性的具体参数对像(包括属性名称,属性类型等等)。

示例二:

class Preference<T>(val context: Context, val name: String, val default: T) : ReadWriteProperty<Any?, T> {

    val prefs by lazy { context.getSharedPreferences("default", Context.MODE_PRIVATE) }

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return findPreference(name, default)
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(name, value)
    }

    private fun <U> findPreference(name: String, default: U): U = with(prefs) {
        val res: Any = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }

        res as U
    }

    private fun <U> putPreference(name: String, value: U) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }.apply()
    }
}

使用的时候:

class ExampleActivity : AppCompatActivity(){
    var a: Int by Preference(this, "a", 0)
    
    fun whatever(){
        println(a)//会从SharedPreference取这个数据
        aInt = 9 //会将这个数据写入SharedPreference
    }
}

这样就很方便了,再也不用去重复写getSharedPreference()、commit()、edit()、apply()之类的东西了。


操作符

https://blog.csdn.net/johnny901114/article/details/86706874

https://www.jianshu.com/p/9d421f8101a0

参考资料:

Kotlin 知识梳理 https://www.jianshu.com/p/ab877fe72b40

[扩展函数和扩展属性] https://www.jianshu.com/p/0e45dd01bc6e

[kotlin属性代理]https://www.jianshu.com/p/f162a4ec6923

[委托模式(Delegate)和委托属性(Delegate Properties] https://www.jianshu.com/p/f54ff17425b2

[kotlin扩展函数]https://www.jianshu.com/p/25332d9a77e0

[Kotlin中的一些常用关键字以及特性] https://www.jianshu.com/p/4f8cd18dfdec

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值