kotlin中的一些常规使用

73 阅读2分钟

前言

方法支持默认参数:

fun toast(context: Context = this, text: String, time: Int = Toast.LENGTH_LONG) {
   Toast.makeText(context,text,time).show()
}

fun test(){
   toast(text = "土司提示")
   toast(this, text = "土司提示")
   toast(this, text = "土司提示", Toast.LENGTH_SHORT)
}

类方法扩展:

// 扩展String类的方法
private fun String.handle(): String {
    return "$this handle"
}

fun main() {
    println("Test".handle())
}

函数变量:

var result = fun(number1: Int, number2: Int): Int {
    return number1 + number2
}

@Test
fun main() {
    println(result(1, 2))
}

内联函数

fun main() {
    // 参数是函数类型的
    showToast({ println("test") }, "test")
}

/**
 * 内联函数用inline修饰:
 * 编译的时候将所有的inline里的代码直接copy进去。方法调用栈减少。
 * 适合:对性能的影响微不足道。适用于参数为函数类型的函数(lambda)。
 * 不适合:一些频繁调用的函数(很多地方都在调用)或者体量比较大的函数,copy会增加代码量
 *
 */
private inline fun showToast(function: () -> Unit, message: String) {
    function.invoke()
    println(message)
}

参数是函数类型的函数,不加inline会导致多生成一个内部类,是lambda函数多出来的类,并且还是静态,会增加内存消耗,inline可以减少一层方法栈的调用(虽然对性能微不足道)。

inline(内联)和noinline(进制内联)。noinline是修饰在lambda参数上面,inline函数有多个lambda参数,只对某个lambda参数不内联,可以用noinline修饰。

private inline fun showToast(function1: () -> Unit,noinline function2: () -> Unit, message: String) {
    function1.invoke()
    function2.invoke()
    println(message)
}

密封类

fun main() {
    val result = if (isDebug) {
        Result.SUCCESS("get data success")
    } else Result.FAIL("get data fail")
    when (result) {
        is Result.SUCCESS -> {
            println(result.data)
        }

        is Result.FAIL -> {
            println(result.throwable)
        }
    }
}

/**
 * 密封类(可以带参数,根据需要修改) 类似于java的枚举(类型固定,不能带参数)
 */
sealed class Result {
    data class SUCCESS(val data: String) : Result()
    data class FAIL(val throwable: String) : Result()
}

类委托

fun main() {
    val logStrategyImpl = LogStrategyImpl()
    LogStrategyProxy(logStrategyImpl).log("test")
}

/**
 * 接口
 */
interface ILogStrategy{
    fun log(msg:String)
}

/**
 * 实现ILogStrategy接口
 */
class LogStrategyImpl:ILogStrategy{
    override fun log(msg: String) {
        println(msg)
    }
}

/**
 * 类委托:把LogStrategyProxy对ILogStrategy实现,委托给参数strategy来实现。所以LogStrategyProxy虽然是接口ILogStrategy
 * 的子类,但是内部不需要自己区实现,把实现委托给自己的参数来实现。
 */
class LogStrategyProxy(strategy: ILogStrategy):ILogStrategy by strategy

属性委托

fun main() {
    // 属性委托 temp对象的创建委托给XxxDelegate类来做。
    var temp: String by XxxDelegate()
    println("temp:$temp")
    temp = "555"
    println("temp:$temp")
}

class XxxDelegate {
    private var currentValue: String = "default"
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        print("getValue $currentValue")
        return currentValue
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: String) {
        currentValue = newValue
        println("setValue $currentValue")
    }
}

懒委托

fun main() {
    // 懒委托:和懒汉式类似
    val temp: String by lazy {
        println("init")
        return@lazy "555"
    }
    println("temp:$temp")
}


// 懒委托最适合用findViewById
private val textView:TextView?by lazy { 
    findViewById(R.id.main)
}

懒委托几种加载模式:

  1. LazyThreadSafetyMode.SYNCHRONIZED:同步模式,确保只有单线程可以初始化实例,初始化时线程安全的,默认使用这种模式。
  2. LazyThreadSafetyMode.PUBLICATION:并发模式,在多线程允许并发初始化,但是只有第一个值返回的值作为实例,这种模式下时线程安全的,多线程并发访问效率最高,空间换取时间,那个线程快就先返回哪个,其他线程执行结果抛弃。
  3. LazyThreadSafetyMode.NONE:普通模式,不会用锁来线程多线程访问,线程不安全的,请勿在多线程并发情况下使用。

使用懒委托变量必须声明为val(不可变),因为它只能被赋值一次。

高阶函数

高阶函数是kotlin简化代码的写法:let with run apply also五个常用函数。

let函数

fun main() {
    // 函数块里用it指代该对象,函数最后一行return返回。
    // 处理针对一个可null对象一些列操作:.?let{}
    val result = "test".let {
        println("it:$it")
        1000
    }
    println("result:$result")
}

with 函数

fun main() {
    // with函数内用this(可省略调用该对象的属性)指代该对象,最后一行是返回值
    // 可以省略类名重复,例如:RecyclerView.onBinderViewHolder中,数据model的属性映射到UI上
    val result = with(Person("test",100)){
        println("name:${this.name} age:$age")
        1000
    }
    println("result:$result")
}
class Person(var name:String,var age:Int)

run函数

fun main() {
    val person = Person("test",18)
    /**
     * run适合于let,with函数任何场景。
     */
    val result = person.run { 
        println("name:$name")
        1000
    }
    println("result:$result")
}
class Person(var name:String,var age:Int)

apply函数

fun main() {
    // apply返回对象本身
    // 如:inflate一个xml的view,并返回View。多层级判空等
    val person = Person("test",18).apply { 
        name = "test1"
        age = 20
    }
}

also函数

fun main() {
    // also 返回值是传入对象本身。一般用于链式调用
    val result = "test".also { 
        println(it.length)
    }
    println("result:$result")
}

运算符重载

fun main() {
    val a = 1
    val b = 2
    // a++
    a.inc()
    // a--
    a.dec()
    // a+b
    a.plus(b)
}