Kotlin 变量、常量、构造方法、函数、协程、非阻塞式挂起、单例、顶层声明

声明变量

Kotlin 空安全机制会限制你在定义变量时不及时赋值,但若此时你还无法及时赋值,可使用 lateinit 关键字修饰,编译器将暂时放弃校验它,但之后的空判断都需要自己检测了

lateinit var someStr : String

当然了,你同样可以通过先赋初始值,之后更新的方式

var someIndex : Int = 0

若有些变量不可避免的会出现赋值为 null 的情况是,可通过 ? 字符设置此变量可为 null

var someStr : String? = null
var someIndex : Int ? = null

使用 val 关键字同样可以定义变量,但它代表只读变量

val className = "SOME_CLASS_NAME"

可以看到我并没有写 : String 但不会报错,这是因为 Kotlin 会自动做类型推断


声明常量

定义常量可通过 const 关键字,且只能修饰 val 类型

const val className = "SOME_CLASS_NAME"

声明静态变量 / 常量

companion object 代码块中可定义静态变量、常量

    companion object {
        val className = "SOME_CLASS_NAME"
        var classId = -1
    }

声明方法

使用 fun 关键字可声明方法,若此方法参数不可为 null 且无返回值:

// Unit 可省略
fun initView(context : Context) : Unit{
       // do something
}

fun initView(context : Context) {
       // do something
}

若此方法参数可为 null 且有返回值,则需在参数后加 ?,并在方法体前加入返回值类型,如 String

fun initView(context : Context?) : String{
       // do something
       return ""
}

声明构造函数

使用 constructor 关键字即可声明构造函数

    var someStr : String = ""

    constructor(someStr:String){
        this.someStr = someStr
    }

并可通过 init 关键字声明初始化代码块

    var someStr : String? = null

    constructor(someStr:String){
        this.someStr = someStr
    }
    
    init {
        // do something
    }

同时还有另一种方法可更方便的实现类初始化,那就是在 class xxx 后直接设置 constructor()

class KotlinTest constructor(someStr : String?, someIndex : Int){
}

顶层声明

将 变量、常量、方法等直接写至 package 下而非 class 内,这样调用时即可

package xxx.xxx.xxx.xxx

val newTimeData = "sometime"
fun getNewTime() = "do something"

object SomeUtils{
    // do something
}

// 调用
var teseData01 = newTimeData
var teseData02 = getNewTime()

companion object 更方便,类名都不用写,鼓掌!

如果留意 getNewTime() 你会发现他只用了一行就完成了所有工作,这是因为 Kotlin 支持这种代码简化的方式:如果你的代码块只有一行,那么可以这样省略


单例模式

若使用 object 关键字修饰某个类的话,则表示它是一个单例类

object SomeUtils{
    val className = "SomeUtils"
    public fun getName() = this.className
}

在其他类中可直接这样调用其方法

var name = SomeUtils.getName()

使用 object 关键字修饰类时,此类中的方法全部为静态方法


协程

一套由 Kotlin 官方提供的线程 API,更加方便的线程框架suspend 可实现非阻塞式挂起,使得并发任务的操作难度大大降低,且能通过 whitContext 消除回调嵌套,解决回调地狱问题。最有特点的是:能够在同一个代码块实现进行多次线程切换

添加依赖地址

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
GlobalScope.launch(Dispatchers.Main) {
    val userInfo = getUserInfo() // 请求数据
    userInfoTv.text = userInfo // UI 更新
}

多接口并行请求完成后合并数据

GlobalScope.launch(Dispatchers.Main) {
    val userInfo = getUserInfo() // 请求数据
    val logo = getLogo() // 请求数据
    val user = userDataUpdate(userInfo, logo) // 合并
    show(user) // 显示
}

whitContext 消除回调嵌套

GlobalScope.launch(Dispatchers.Main) {
    
    val logo = withContext(Dispatchers.IO){
        getLogo() // 请求数据
    }

    val name = withContext(Dispatchers.IO){
        getName() // 请求数据
    }
    // ···
}

也可这样写,跟上边的方式结果相同

GlobalScope.launch(Dispatchers.Main) {
    val logo = spendingGetLogo()
    logoIv.setImageBitmap(logo)
}

suspend fun spendingGetLogo(){
    withContext(Dispatchers.IO){
        getLogo() // 请求数据
    }
}

协程挂起

挂起后协程暂时从线程脱离,若此线程非主线程之后线程会被回收或再利用,若此线程是主线程那么主线程继续执行之后的代码。但方法会切换至新指定线程中继续执行,且当方法执行完毕后,线程会自动切会原线程,所以挂起的本质就是切线程处理,完成后自动切回原线程

为什么挂起函数只能在协程,或另一个协程里调用?

挂起后需要恢复,也就是切回原线程,恢复的功能是属于协程的,所以被挂起的函数如果不是在协程中调用,也就无法实现恢复

怎么挂起?

withContext(Dispatchers.xxx) 内部包含有自带的挂起函数,

suspend 的作用?

函数的 创建者对函数的调用者提醒,表示这是一个耗时函数,所以创建者用挂起的方式放在后台运行,所以要调用我的话得在协程里。

怎么自定义 suspend 函数?

当此函数比较耗时,就把它定义为挂起函数,如I/O、计算或等待(网络通信也属IO的一种)

suspend fun xxx(){
  withContext(Dispatchers.xxx){
    // do something
  }
}

协程非阻塞式挂起

非阻塞式表示当前线程不卡顿,协程可以用看似阻塞的代码做到非阻塞的处理操作

Java中线程切换也是非阻塞式的,但它跟协程挂起的区别在于:单线程的耗时操作会产生阻塞,而协程可以利用挂起函数将耗时操作切换至另一个线程继续处理

不过从协程的写法上来看,两行代码连续写的方式好像是同一线程在处理的,但实际上已经被切换线程继续处理,只不过处理完成后又自动切回来原线程,而这个过程无法肉眼感知


若您有遇到其它相关问题,非常欢迎在评论中留言,我和其他读者小伙伴们将帮助解决并持续更新至此文,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!推荐 朱凯老师(扔物线)的 Kotlin 学习网站:https://kaixue.io,棒!

发布了94 篇原创文章 · 获赞 387 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_15609303/article/details/103146216
今日推荐