KMM Kotlin expect的几种声明方式

前言

Kotlin的expect关键字一般用在多平台上,比如在多平台项目中的common中声明方法签名,然后由不同的平台去实现该方法,从而实现一个多平台(跨平台)方法.

创建KMM项目可以参考: KMM(二)+Compose(二) 开发一个Kotlin多平台应用_滔lt的博客-CSDN博客

正文

接下来就说一下Kotlin expect的几种声明方式

1.顶层函数和顶层扩展函数

在commonMain文件夹中声明:

在androidMain(和其他平台)文件夹中实现:

声明并实现后,不管是共享代码还是平台代码中都可以使用相应方法

2.属性

 声明:

expect val isDebug: Boolean

 实现:

actual val isDebug: Boolean = BuildConfig.DEBUG

3.注解

声明:

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
internal expect annotation class ExpectAnnotation()

实现:

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
internal actual annotation class ExpectAnnotation()

4.枚举

声明:

expect enum class Enum

实现:

actual enum class Enum {
    enum1,
    enum2,
    enum3,
}

5.接口

声明:

expect interface Interface {
    fun fun1()
    fun fun2(): String
}

实现:

actual interface Interface {
    actual fun fun1()
    actual fun fun2(): String
    fun fun3() {
        "fun3".loge()
    }
}

6.类

声明:

expect class Class() {
    fun fun1()
    fun fun2(): String
}

实现:

actual class Class {
    actual fun fun1() {

    }

    actual fun fun2(): String {
        return getUUID()
    }
}

经测试,sealed class可以,data class好像用不了

ps:在公共模块使用接口和类暂时需要手动导包

7.typealias

使用kotlin的typealias特性,我们可以将一个已经实现类映射为expect的实现

我们接下来实现一个多平台的ViewModel

先去common目录下的build.gradle.kts文件中

添加viewmodel的依赖:

        val androidMain by getting {
            dependencies {
                api("androidx.appcompat:appcompat:1.2.0")
                api("androidx.core:core-ktx:1.3.1")
                api("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")//增加vm依赖
            }
        }

声明:

expect open class MViewModel() {
    protected open fun onCleared()
}

androidMain实现(直接使用ViewModel):

import androidx.lifecycle.ViewModel

open class MyViewModel : ViewModel() {
    override fun onCleared() {
        super.onCleared()
    }
}

actual typealias MViewModel = MyViewModel

ps:这里说一下为什么要实现一下ViewModel才使用 typealias,首先ViewModel是个抽象类,但又没必要搞成抽象的,最重要的是Kotlin的protected和Java的protected可见性不同,所以导致typealias无法直接匹配上,不知道Kotlin后续要怎么补上这个坑,参考下图和文章:

学习Kotlin(三)类和接口_滔lt的博客-CSDN博客

desktopMain实现: 

actual open class MViewModel {
    protected actual open fun onCleared() {
    }
}

上面代码放在了Github的expects目录: ltttttttttttt/KMM_and_Compose_Sample

参考Kotlin官网: Connect to platform-specific APIs | Kotlin

如有错误欢迎大佬们指出

end

猜你喜欢

转载自blog.csdn.net/qq_33505109/article/details/123560909