Kotlin Multiplatform--04:经验总结(持续更新)

Kotlin Multiplatform--04:经验总结(持续更新)

引言

本章用来记载笔者开发过程中的一些经验总结


一、Ktor设置Header

官方文档中,想要设置Header的示例代码如下:

kotlin 复制代码
client.get("https://ktor.io") {
    headers {
        append(HttpHeaders.Accept, "text/html")
        append(HttpHeaders.Authorization, "abc123")
        append(HttpHeaders.UserAgent, "ktor client")
    }
}

但经过笔者多次测试和踩坑,在最新版本的Ktor中,这样设置Header根本没用,需要用以下代码设置:

kotlin 复制代码
client.get("https://ktor.io") {
    headers["User-Agent"] = "ktor client"
}

二、IO与ViewModel

ViewModel是Android开发中一个很重要的概念,因为它的存活时间相较于StateHodler更长,所以最适合用来处理业务逻辑。普通的ViewModel不能有任何参数,如下所示:

kotlin 复制代码
class MyViewModel: ViewModel() { ... }

由于ViewModel存活时间长,因此它不能直接引用Context对象,更不能被其他对象引用。定义了自己的MyViewModel类后,通过以下函数引用MyViewModel对象,哪里需要就在哪里调用,如果没有这个函数,则需要添加以下依赖:

kotlin 复制代码
// androidx.lifecycle:lifecycle-viewmodel-compose
val myViewModel: MyViewModel = viewModel()

当viewModel中需要涉及文件读写等IO操作时,可以使用viewModelScope和withContext切换到IO线程,防止阻塞UI。示例代码如下:

kotlin 复制代码
class MyViewModel: ViewModel() {
    fun save(context: Context) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "data.json").outputStream().use {
                    it.write(...)
                }
            }
        }
    }
}

三、测量与布局

IntrinsicSize 用于控制组件的 固有尺寸测量(intrinsic measurement),它允许你在布局过程中获取或使用组件的固有宽度或高度。当需要根据子组件的尺寸来约束父组件大小时,可以使用IntrinsicSize实现。

例如我有一个父组件Box和两个子组件Row,其中包含Text组件的Row大小已知,需要让另一个Row大小一致,此时可以用如下代码实现:

kotlin 复制代码
 Box(Modifier.height(IntrinsicSize.Min)) {
     Row {
         Text(value, fontSize = TextUnit(26f, TextUnitType.Sp))
     }
     Row(Modifier.fillMaxSize()) {
         ...
     }
 }

注意事项:

1、固有尺寸计算可能会有性能开销,应避免在性能敏感的场景过度使用。

2、并非所有组件都支持固有尺寸(如 LazyColumn 就没有固有高度)。

四、回调与协程

回调函数是非常常见的一种编程范式,在Java中尤为突出。但回调函数一多就会形成回调地狱,不管是开发还是维护都十分痛苦。Kotlin为了解决这一痛点,设计了suspendCoroutine。suspendCoroutine 是 Kotlin 协程中的一个核心函数,用于将传统的基于回调的异步操作转换为协程风格的挂起函数。示例代码如下所示:

kotlin 复制代码
// 模拟常见的回调函数
fun someCallbackFun(callback: (String) -> Unit) {
    callback("myCallback")
}

// 正常调用方法
fun callBackMain() {
    someCallbackFun { 
        println(it)
    }
}

// 协程调用,将非线性程序转为线性程序
suspend fun coroutineMain() {
    val retval = suspendCoroutine { coroutine ->
        someCallbackFun {
            coroutine.resume(it)
        }
    }
    print(retval)
}
相关推荐
喜欢吃燃面6 分钟前
C++算法竞赛:位运算
开发语言·c++·学习·算法
草莓熊Lotso10 分钟前
《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
开发语言·c++·经验分享·笔记·其他
谱写秋天16 分钟前
Qt 5.5 的安装与配置(使用 VSCode编辑)
开发语言·vscode·qt
项目申报小狂人18 分钟前
算法应用上新!自适应更新策略差分进化算法求解球形多飞行器路径规划问题,附完整MATLAB代码
开发语言·算法·matlab
阿珊和她的猫4 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
fouryears_234177 小时前
Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析
开发语言·flutter·客户端·dart
我好喜欢你~7 小时前
C#---StopWatch类
开发语言·c#
lifallen9 小时前
Java Stream sort算子实现:SortedOps
java·开发语言
IT毕设实战小研9 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计