
kotlin
文章平均质量分 91
Android kotlin 语言学习系列
川峰
8年+Android相关工作经验。专注于移动开发领域。
展开
-
Kotlin 协程中容易让人忽视的 Cancellation 陷阱
启动的协程作用域没有被真正取消,这与我们的预期不符,当用户按下返回键关闭页面时,我们期望的是取消协程中正在后台执行的上传任务,否则这容易导致内存泄漏。,该异常不会取消它的父协程,这个异常通常会被忽略静默处理,但是假如你捕获了该异常,那么父协程就不会感知到任何取消通知,也就不会取消协程。注意,检测协程是否被已被取消,最好是在循环中,或者如果没有循环逻辑则每隔一段代码调用一次检测,所以上面读取文件的代码最好不要使用。这个示例的问题在于,协程的取消可以是在任何时机,不一定在某个方法当中,例如在。原创 2024-02-26 08:21:55 · 1365 阅读 · 0 评论 -
使用 Koltin 集合时容易产生的 bug 注意事项
可以看到这个问题的解决并非难事,非常简单,困难的是如何发现这种问题,如果没有并发安全的意识,可能只能对着应用抛出的异常日志发呆而无从下手。所以,如果你没有意识到集合类可能在多线程下导致的并发安全问题,一旦产生这样的bug或异常,就会很棘手,很难发现问题的原因。的消息了,因为被线程 1 删除了一个,消息列表不够 4 个了,这种情况下,你的应用可能会得到某种类似于。类的相关方法,那么不会有任何问题,但是假如你在多个线程中调用这个类,比如在线程池中跑,那就不一定了。类那样,每次操作都会产生一个新的不可变。原创 2024-02-27 07:30:00 · 603 阅读 · 0 评论 -
3 个Android Kotlin 小技巧教你做人:好的编码习惯胜过好的编码技术
在没有使用 Kotlin 之前,使用Java的时候,或许你有封装过一些工具类来做类似的事情,但是下面我们看一下如何通过 Kotlin 的属性代理的方式来简化类似这种读写数据的逻辑。中读取的,这样将读写的逻辑隐藏在了背后,开发者只需要读,但不需要关心具体是怎么读的,能够更好的把精力放在纯业务问题上。),但这不并妨碍本文以此作为示例来演示问题所在,如果你有其他的比较复杂的读写逻辑想要简化,其实处理方式是类似的。现在的问题是,如果这个接口的调用者在不看注释的情况下,如何知道这个方法的返回值代表的是一个。原创 2024-02-26 07:30:00 · 1205 阅读 · 0 评论 -
《Kotlin核心编程》笔记:设计模式
主流的创建型模式有:工厂方法模式、抽象工厂模式、构建者模式在有些地方会把工厂模式细分为简单工厂、工厂方法模式以及抽象工厂。这里主要介绍简单工厂的模式,它的核心作用就是通过一个工厂类隐藏对象实例的创建逻辑,而不需要暴露给客户端。典型的使用场景就是当拥有一个父类与多个子类的时候,我们可以通过这种模式来创建子类对象。假设现在有一个电脑加工厂,同时生产个人电脑和服务器主机。我们用熟悉的工厂模式设计描述其业务逻辑:以上代码通过调用类的方法来创建不同的子类对象,这样我们就把创建实例的逻辑与客户端之间实现解耦,当对象创原创 2023-12-17 12:00:00 · 1119 阅读 · 0 评论 -
《Kotlin核心编程》笔记:反射、注解和加锁
通过上面的运行结果我们发现,对于属性和无参数的函数,它们都有一个隐藏的参数为类的实例,而对于声明参数的函数,类的实例作为第 1 个参数,而声明的参数作为后续的参数。由于 Kotlin 兼容 Java,所以所有 Java 可以添加注解的地方,Kotlin 也都可以。通过上面对比我们发现,Kotlin 和 Java 注解整体上是保持一致的,熟悉 Java 注解的读者应该很容易将这部分知识迁移到 Kotlin。顾名思义就是目标对象,也就是我们定义的注解能够应用于哪些目标对象,可以同时指定多个作用的目标对象。原创 2023-12-16 22:43:05 · 1242 阅读 · 2 评论 -
《Kotlin核心编程》笔记:特设多态、运算符重载和扩展函数
一切看起来都很顺利,但是当我们想让第三方类库也支持这样的写法时,我们发现,并不是所有的第三方类库中的类都存在伴生对象,我们只能通过它的实例来进行调用,但这样会造成很多不必要的麻烦。这样就为我们带来了一个很大的好处,即被扩展的第三方类免于被污染,从而避免了一些因父类修改而可能导致子类出错的问题发生。,而 Java 的静态方法的特点就是:独立于该类的任何实例对象,且不依赖类的特定实例,被该类的所有实例共享。的实例不一定支持加法操作,而且如果针对一些自定义类,我们更希望能够实现各自定制化的“加法语义上的操作”。原创 2023-12-16 19:30:31 · 437 阅读 · 0 评论 -
《Kotlin核心编程》笔记:集合、序列与内联函数
这是因为 Java 8 的流和 Kotlin 中的序列一样,也是惰性求值的,这就意味着 Java 8 的流也是存在中间操作和末端操作的(事实也确实如此),所以必须通过上面的一系列转换才行。我们知道序列是惰性求值的,所以上面创建的序列是不会把所有的自然数都列举出来的,只有在我们调用一个末端操作的时候,才去列举我们所需要的列表。仔细看看上面的结果,我们可以发现一些有趣的地方。另外,由于kotlin和Java是兼容的,可以互相调用的,而在Java中是不区分只读集合与可变集合的,这就很容易出现修改只读集合的情况。原创 2023-12-16 16:55:29 · 853 阅读 · 0 评论 -
《Kotlin核心编程》笔记:可空类型&平台类型&装箱类型&数组类型&泛型&协变与逆变
不是同一种列表,后者可以添加任意元素,而前者只是通配某一种类型,但是编译器却不知道这是一种什么类型,所以它不允许向这个列表中添加元素,因为这样会导致类型不安全。这里的意思相当于,在编译的会将具体的类型插入相应的字节码中,那么我们就能在运行时获取到对应参数的类型了。Kotlin中的内联函数在编译的时候编译器便会将相应函数的字节码插入调用的地方,也就是说,参数类型也会被插入字节码中,我们就可以获取参数的类型了。Kotlin 中的泛型机制与 Java 中是一样的,所以上面的特性在 Kotlin 中同样存在。原创 2023-12-16 00:56:32 · 1611 阅读 · 0 评论 -
《Kotlin核心编程》笔记:面向对象
而 Kotlin 默认并没有采用这种包内可见的作用域,而是使用了模块内可见,模块内可见指的是该类只对一起编译的其他 Kotlin 文件可见。需要注意的是,由于参数默认值的存在,我们在创建类对象时,最好指定参数的名称,否则必须按照实际参数的顺序进行赋值。注意:Kotlin 1.0 的时候,密封类的子类只能定义在父类结构体中,而 Kotlin 1.1 之后可以不用将子类定义在父类中了。定义的内容都可以用 Kotlin 中的伴生对象来实现。然而,它们是类似的,一个类的伴生对象跟一个静态类一样,全局只能有一个。原创 2023-12-15 22:44:00 · 1328 阅读 · 0 评论 -
《Kotlin核心编程》笔记:面向表达式编程
由于每个表达式都具有值,并且也可以将另⼀个表达式作为组成其自身的⼀部分,所以我们可以写出⼀个复合的表达式。一个很大的原因是函数式编程侧重于组合,尤其是很多高阶函数,在源码实现的时候都是采用泛型来实现的。关键字,但与 Java 的枚举不同的是,由于它是⼀种类,它可以拥有构造参数,以及定义额外的属性和方法。相比语句而言,表达式更倾向于自成⼀块,避免与上下文共享状态,互相依赖,因此我们可以说它具备更好的。分支也必须被考虑,这很容易理解,因为表达式具备类型信息,最终它的类型就是。可以看出,基于表达式的方案彻底。原创 2023-12-15 10:55:31 · 420 阅读 · 0 评论 -
Kotlin 笔记 -- Kotlin 语言特性的理解(二)
当 lambda 当作函数参数进行传递时,它本质上是一个函数对象,最终要将上述代码翻译成 Java 的字节码,而在 Java 中是没有函数对象这种东西的,那么怎么办呢?在函数是一等公民的世界里,策略模式变得没有意义,或者说不用写专门的代码去实现它,因为函数类型天生就支持返回不同的类型。的分支抛出了异常,抛出异常就属于函数的副作用,它会打破原有的业务逻辑,对外部调用者来说,对该函数的期望是返回。选择一门支持函数式编程的语言,并不是写出函数式代码的关键,转变看待问题的角度才是最重要的。原创 2023-12-15 07:51:12 · 1277 阅读 · 0 评论 -
Kotlin 笔记 -- Kotlin 语言特性的理解(一)
双冒号对函数进行引用的本质是生成一个函数对象只有函数对象才拥有invoke()方法,而函数是没有这个方法的kotlin中函数有自己的类型,但是函数本身不是对象,因此要引用函数类型就必须通过双冒号的方式将函数转换成一个对象,这样之后才能拿这个对象进行赋值匿名函数是一个对象,它不是函数匿名函数跟双冒号引用函数是一种东西而 lambda 表达式是一种特殊的匿名函数对象,它可以省略参数和调用者括号等,更加方便而已因为匿名函数是一个对象,所以它(包括lambda表达式)才可以被当成一个参数传递双冒号函数引原创 2023-12-14 22:57:46 · 1313 阅读 · 0 评论 -
kotlin 基础概览
可以通过类委托的模式来减少继承类委托的,编译器会优先使用自身重写的函数,而不是委托对象的函数。如果我们在构造器主动调用了父类构造,那么在继承类的时候就不能在类的后面。所以在写内联函数的时候需要注意,尽量将内联函数中的代码行数减少!中,我们可以声明抽象属性,子类对抽象属性重写的时候需要重写对应的。内联函数配合「函数类型」,可以减少「函数类型」生成的对象。在「编译时」会将「内联函数」中的函数体直接插入到调用处。函数类型由「传入参数类型」和「返回值类型」组成,用「在类型后面加上一个感叹号的类型是「平台类型」原创 2023-12-14 18:11:37 · 919 阅读 · 0 评论 -
Kotlin学习笔记——类、接口、扩展方法、空类型
定义类和构造方法:class SimpleClass(var x: Int, val y: String){}//创建类不需要new关键字val simpleClass = SimpleClass(9, "Hello")构造方法放在类名的后面,如果x和y前面加了var或val, x和y会分别在类中定义一个属性以及对应的getter和setter方法,不需要额外写,否则必须手动写getter和setter实现。类前面不需要修饰符public private等,跟java不一样,默认是publi.原创 2020-12-11 23:17:23 · 764 阅读 · 1 评论 -
【深入理解Kotlin协程】协程的创建、启动、挂起函数【理论篇】
kotlin实现恢复挂起点是通过一个接口类Continuation(英文翻译过来叫"继续、延续、续体")来实现的。Kotlin 续体有两个接口:Continuation和CancellableContinuation, 顾名思义CancellableContinuation是一个可以取消的Continuation。原创 2022-11-11 08:42:27 · 1519 阅读 · 0 评论 -
【深入理解Kotlin协程】CoroutineScope.launch源码追踪扒皮
coroutine.start的调用涉及到运算符重载,实际上最终会调到CoroutineStart.invoke()方法,在这个方法中根据当前的启动模式去分别执行不同方法,默认的启动模式是DEFAULT,因此这里走第一个分支。同时注意到,DEFAULT模式下,这里startCoroutineCancellable方法的receiver和completion参数都是StandaloneCoroutine对象。在协程体的逻辑执行完后会调用到completion的resume方法恢复后面...原创 2022-11-15 16:36:03 · 2574 阅读 · 0 评论 -
【深入理解Kotlin协程】lifecycleScope源码追踪扒皮
lifecycleScope是LifecycleOwner的扩展属性,而ComponentActivity和Fragment(androidx)都实现了LifecycleOwner接口,所以这就是为什么说lifecycleScope的作用范围是只能在Activity、Fragment中使用。其中lifecycle.coroutineScope又是Lifecycle的扩展属性.......原创 2022-11-15 15:55:24 · 1092 阅读 · 0 评论 -
【深入理解Kotlin协程】协程的上下文 CoroutineContext
CoroutineContext使用以下元素集定义协程的行为:Job:控制协程的生命周期。CoroutineDispatcher:将工作分派到适当的线程。CoroutineName:协程的名称,可用于调试。CoroutineExceptionHandler:处理未捕获的异常。launch、async、runBlocking 等启动协程方式第一个参数都是需要传入一个协程上下文,当然默认的都是EmptyCoroutineContext。原创 2022-11-11 09:16:17 · 792 阅读 · 1 评论 -
【深入理解Kotlin协程】使用Job控制协程的生命周期
Job 是协程上下文CoroutineContext的实现之一,我们通过Job可以获取当前协程的运行状态,还可以随时取消协程。Job 是协程的 句柄。使用 launch 或 async 创建的每个协程都会返回一个 Job 实例对象,该实例是相应协程的唯一标识并管理其生命周期。还可以将 Job 传递给 CoroutineScope 以进一步管理其生命周期。原创 2022-11-15 15:05:29 · 2051 阅读 · 0 评论 -
【深入理解Kotlin协程】协程中的Channel和Flow & 协程中的线程安全问题
Channel 实际上就是 个并发安全的队列,它可以用来连接协程,实现不同协程的通信,代码如代码清单所示上述代码 构造了两个协程 producer 和 consumer, 没有为它们明确指定调度器,所以它们都是采用默认调度器,在 Java 平台上就是基于线程池实现的 Default。 它们可以运行在不同的线程上,也可以运行在同一个线程上,具体执行流程如图 6-2 所示。producer 每隔 1s 向 Channel 发送 1 个数,consumer 一直读取 channel 来获取这个数字并打印,显原创 2022-11-15 21:31:26 · 2215 阅读 · 0 评论 -
【深入理解Kotlin协程】协程的分类、与线程的区别
线程是属于操作系统的概念,而协程则属于编程语言的范畴,它属于应用程序层的Api层的东西,可以运行在线程框架之上,由线程框架在背后操作代码的调度。原创 2022-11-11 08:00:00 · 1289 阅读 · 0 评论 -
《Kotlin核心编程》笔记:val 和 var & 字符串
重要原则:优先使用val来声明变量。更好的理解可以是:尽可能采用val、不可变对象及纯函数来设计程序。 因为引用不可变,val声明的变量只能被赋值一次,且在声明时不能省略变量类型。在Kotlin编程中,我们推荐优先使用val来声明⼀个本身不可变的变量,这在大部分情况下更具有优势:这是⼀种防御性的编码思维模式,更加安全和可靠,因为变量的值永远不会在其他地方被修改,不可变的变量更易推理,越是复杂的业务逻辑,它的优势就越⼤。既然有了val, 为什么还要使用var?因为var有更好的性能,占用内存更小。所以原创 2023-01-06 07:30:00 · 1639 阅读 · 0 评论 -
【深入理解Kotlin协程】Google的工程师们是这样理解Flow的?
Question:why there is a Flow in kotlin?问这个问题就好比在问为什么那里会有一座山存在,嗯,这貌似是一个哲学问题。当然,对于kotlin中的Flow的理解可能不会上升到这么高的哲学层次,对于Flow相关的Api掌握并使用它并不是什么难事,但是我们需要思考的是为什么会有Flow这样的存在?原创 2022-11-23 17:55:24 · 892 阅读 · 0 评论 -
【深入理解Kotlin协程】如何将回调改写成挂起函数
使用suspendCoroutine获取挂起函数的Continuation回调成功的分支使用Continuation.resumeWith(value)回调失败的分支则使用Continuation.resumeWithException(e)只不过真正的挂起需要真正的切换线程,如果直接调用的话相当于没有挂起。原创 2022-11-15 14:35:41 · 511 阅读 · 0 评论 -
《Kotlin核心编程》笔记:高阶函数和 Lambda 表达式
函数式语言⼀个典型的特征就在于函数是头等公民——我们不仅可以像类⼀样在顶层直接定义⼀个函数,也可以在⼀个函数内部定义⼀个局部函数原创 2023-01-07 07:30:00 · 988 阅读 · 1 评论 -
Kotlin 元编程之 KSP 实战:通过自定义注解配置Compose导航路由
在之前Jetpack Compose中的导航路由一文中,我提到开源库 compose-destination 就是借助 KSP 来生成代码的,如果你去看它的源码,就会发现它是通过纯KSP的方式生成代码的,没有使用KotlinPoet。下面通过 KSP + KotlinPoet 的方式也来自定义实现一个下简单的可以通过注解配置的Compose导航路由框架。当然,实现思路最终还是要通过Compose原生的导航路由API来实现,只不过我们可以对其进行一些封装,隐藏那些烦人又麻烦的配置操作细节。具体的思路是原创 2023-01-18 12:30:00 · 2725 阅读 · 0 评论 -
Kotlin 元编程之 KotlinPoet
在 KSP 中默认生成代码的方式是通过创建文件流后以字符串拼接的方式来生成代码,对于简单的demo还好,但是对于实际生产项目中要生成的代码可能会十分复杂,如果还是自己手动去拼接,可能非常的繁琐,累死人不说,还非常容易出错,比如说少拼接了一个标点符号,可能需要排查半天。实际生产项目中使用的最多的就是由 JakeWharton 大神所写的著名的开源库(很有诗意的名字,翻译过来叫Java诗人)使用该库可通过方便的函数进行拼接,减少出错。原创 2023-01-18 07:30:00 · 1940 阅读 · 0 评论 -
【深入理解Kotlin协程】协程作用域、启动模式、调度器、异常和取消【使用篇】
当我们创建一个协程的时候,都会需要一个 CoroutineScope ,我们一般使用它的 launch 或 async 函数去进行协程的创建。 CoroutineScope 会跟踪它使用 launch 或 async 创建的所有协程。您可以随时调用 scope.cancel() 以取消正在运行的协程。不过,与调度程序不同,CoroutineScope 不运行协程,它只是确保您不会失去对协程的追踪。为了确保所有的协程都会被追踪,Kotlin 不允许在没有使用 CoroutineScope 的情况下原创 2022-11-11 10:59:24 · 3823 阅读 · 0 评论 -
【深入理解Kotlin协程】协程调度器Dispatchers源码追踪扒皮
Android中的Kotlin协程调度器主要有四种:Dispatchers.Main、Dispatchers.Default、Dispatchers.IO、Dispatchers.Unconfined,第四种平时开发应该一般不会用到,所以主要了解一下前3种的实现。原创 2022-11-15 17:23:54 · 1271 阅读 · 0 评论 -
Kotlin 元编程之 KSP 全面突破
没想到吧,这世上除了元宇宙,还有元编程,如果没有接触过,可能会有点懵,不过没关系,简单的说就是用代码来生成代码。实现元编程的传统常见手段主要是使用 APT注解处理器 +JavaPoet组合拳,如果你是作为一名Android 开发者,一定在曾经或者现在使用过很多知名的开源库,比如ARouter等,这些都是基于 注解处理器 +JavaPoet的方式实现的元编程,是的,虽然元编程这个词很高大上,但是可能你已经默默的使用了很多年了。原创 2023-01-18 10:30:00 · 4114 阅读 · 2 评论 -
Kotlin学习笔记——Kotlin基础
Kotlin学习手记——基本类型、变量、集合、数组、区间、函数声明原创 2020-12-11 21:10:20 · 5904 阅读 · 1 评论