Kotlin基础知识点
Posted 刘兆贤
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin基础知识点相关的知识,希望对你有一定的参考价值。
本文来自刘兆贤的博客_CSDN博客-Java高级,Android旅行,Android基础领域博主 ,引用必须注明出处!
Kotlin越来越流行,新的知识点和应用技巧,也十分吸引人,尤其是协程,其他还有规避回调的代码写法(类似RxJava)。
下面是经典写法,比较符合kotlin语法
class Test
public static long plus(int i1, int i2)
return i1 + i2;
public static void main(String[] args)
System.out.println(plus(1, 2));
class Test
interface Continuation
void next(int result);
public static void plus(int i1, int i2, Continuation continuation)
continuation.next(i1 + i2);
public static void main(String[] args)
plus(1, 2, result -> System.out.println(result));
协程,协助线程,而非代替线程。可以在单线程中使用,多线程同样可以,不需要切换到内核(有效降低线程上下文切换所浪费的时间),但需要遵循线程的临界条件,比如不能在主线程做网络请求等费时操作。
下面是顺序代码,无需回调,体现Kotlin的优雅。
launch(
val user = api.getUser() // 👈 网络请求(IO 线程),非阻塞式挂起,不影响后面操作
nameTv.text = user.name // 👈 更新 UI(主线程)
)
其中launch方法有3种
// 方法一,使用 runBlocking 顶层函数
runBlocking
getImage(imageId)
// 方法二,使用 GlobalScope 单例对象
// 👇 可以直接调用 launch 开启协程
GlobalScope.launch
getImage(imageId)
// 方法三,自行通过 CoroutineContext 创建一个 CoroutineScope 对象
// 👇 需要一个类型为 CoroutineContext 的参数
val coroutineScope = CoroutineScope(context)
coroutineScope.launch
getImage(imageId)
方法一,阻塞线程,通常用于单元测试,线上不用。
方法二,生命周期与APP一致,且不能取消,故不推荐。
方法三,推荐使用,其中lanch时,可加入IO/Main等类似RxJava线程类型。
coroutineScope.launch(Dispatchers.IO)
//切到IO线程,执行耗时操作
coroutineScope.launch(Dispatchers.Main)
//切到主线程,执行UI刷新操作
业务流程变成这样
coroutineScope.launch(Dispatchers.Main) // 开始协程:主线程
val token = api.getToken() // 网络请求:IO 线程
val user = api.getUser(token) // 网络请求:IO 线程
nameTv.text = user.name // 更新 UI:主线程
还有一个经典的withContext操作,执行结束返回原线程,避免切换线程的麻烦。
coroutineScope.launch(Dispatchers.Main) //在 UI 线程开始
val image = withContext(Dispatchers.IO) //切换到 IO 线程,并在执行完成后切回 UI 线程
getImage(imageId) //将会运行在 IO 线程
avatarIv.setImageBitmap(image) //回到 UI 线程更新 UI
其他两个等号判断值相等,三个等号判断引用相等。
进程、线程和协程区别:
1、线程是CPU调度的基本单位,受内存大小影响有数量限制,切换发生在内核态,做数据同步时需要加锁。
2、进程是操作系统调度的基本单位,包含线程,线程共享其资源。
3、协程运行在线程中,可以阻断当前函数,切换发生在用户态,节省资源。
线程和协程的应用场景:
1、如果两个线程前后依赖,则可以写到一个协程里(比如两个网络请求的结果,去渲染同一页面)。线程用于独立的、耗时的操作(比如不同的线程往同一个文件里写内容)。
2、由于线程运行耗费CPU资源,多线程适用于计算密集处理。由于协程可切换用户态,多协程适用于IO密集处理。但多协程顺序执行时,前面阻塞,后面也暂停。
怎么做上下文切换?
使用程序计数器,记录切换的位置,返回时恢复方法栈,从上次记录的地方继续执行。
协程上下文(CoroutineContext)切换具体实现:
使用Dispatchers,Main指运行在主线程,IO即IO线程,Default用于简单计算,Unconfined不指定线程的分发器。
newSingleThreadContext使用一个新线程,在结束时要用cancel方法取消,此线程也可以作为复用线程来使用。
Job是launch或async方法返回的协程实例,可用于判断协程是否存活、已取消、已完成等状态和取消协程。
切换原理:
采用hander和方法回调的方式,分别实现切换到主线程,以及其他线程。
LiveData为什么是粘性的?
正常情况下,观察者订阅事件后,非观察者发送事件,观察者才能收到事件。粘性是指,不管观察者什么时候订阅事件,都可以接收到非观察者发送的事件。原因:已经订阅的,勿庸置疑;未事先订阅的,在初始化时拿到LiveData的START_VERSION(-1),每次LiveData改变后,其mVersion(初始值-1)都会加1,设置观察事件后比对Version值不同,则会主动给自己接收一个事件(即值变化)。
番外:EventBus也有类似机制,发送粘性事(stickyEvent)件时,会将此事件的class文件缓存,如果后面观察者再订阅这个事件,同样会先收到一个消息。
Kotlin里的uncaughtExceptionHandler:
CoroutineExceptionHandler,需要在协程初始化的时候使用。
https://blog.csdn.net/u011109881/article/details/120899119
以上是关于Kotlin基础知识点的主要内容,如果未能解决你的问题,请参考以下文章