进入KMP
This commit is contained in:
@@ -96,16 +96,4 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 目前仍存在的问题
|
||||
|
||||
如果直接在gradle中添加我的依赖,那么,可能会出现这样的问题
|
||||
|
||||
```bash
|
||||
C:\Users\32721\AppData\Local\Temp\ffmpegkit_2621802206663535111.dll: %1 不是有效的 Win32 应用程序。
|
||||
at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
|
||||
......
|
||||
```
|
||||
|
||||
目前,我还不知道如何解决,但可以确认的是,拿编译输出的 jar 包直接用作依赖不会出现这样的问题。
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
# Kotlin Springboot
|
||||
|
||||
> 总体上来讲,Kotlin 与 Java 相比是有好有坏的,优点是写起来更简洁,缺点是写起来更简洁。
|
||||
|
||||
## 创建一个 Springboot 项目
|
||||
|
||||
这很简单,在 IDEA 中就可以创建,记得选 Kotlin 和 Gradle kts。
|
||||
@@ -1,32 +0,0 @@
|
||||
# 项目的基本结构
|
||||
|
||||
## 目录
|
||||
|
||||
一般来讲,一个 KMP 项目在生成的时候,长这样
|
||||
|
||||
- /
|
||||
- androidApp/
|
||||
- desktopApp/
|
||||
- iosApp/
|
||||
- webApp/ (JS 已经死了,现在的是 WAMS)
|
||||
- shared/
|
||||
- src/
|
||||
- commonMain/
|
||||
- commonTest/
|
||||
- androidMain/
|
||||
- ......
|
||||
- build.gradle.kts
|
||||
- .gitignore
|
||||
- README.md
|
||||
- gradle 二进制文件(三大平台各一个)
|
||||
- gradle.proporties
|
||||
- local.proporties
|
||||
- build.gradle.kts
|
||||
- settings.gradle.kts
|
||||
|
||||
如果你的项目还要包含 server 的部分的话,那会稍微复杂一点点
|
||||
|
||||
## 各部分用途
|
||||
|
||||
所有的共享的部分(如UI,基础逻辑)都写在 `shared/commonMain` 里面,不同平台如果要做不同的效果,那么,相应的代码写在对应的 `Main` 里面,`App` 目录主要控制打包设置和进入软件的窗口设定,虽然可以写针对不同平台的不同效果,但是不推荐。
|
||||
|
||||
@@ -342,4 +342,6 @@ val a = doOrNull(b) { it.c + 1 }
|
||||
|
||||
[目录](../README.md)
|
||||
|
||||
[下一篇:深入 Kotlin](../深入Kotlin.md)
|
||||
[下一篇:深入 Kotlin](./深入Kotlin.md)
|
||||
|
||||
[进入 KMP](./进入KMP.md)
|
||||
@@ -910,10 +910,12 @@ val copied = user.copy(name = "Bob")
|
||||
println(copied) // User(id=1, name=Bob)
|
||||
```
|
||||
|
||||
`data class` 会自动生成 `toString`、`equals`、`hashCode`、`copy` 等方法,很适合表示简单数据。
|
||||
`data class` 会自动生成 `toString`、`equals`、`hashCode`、`copy` 等方法,很适合表示简单数据。是一个替代 `Lombook` 的好东西。
|
||||
|
||||
## 接下来可以看
|
||||
|
||||
[目录](../README.md)
|
||||
|
||||
[下一篇:深入 Kotlin](../深入Kotlin.md)
|
||||
[下一篇:深入 Kotlin](./深入Kotlin.md)
|
||||
|
||||
[进入 KMP](./进入KMP.md)
|
||||
@@ -0,0 +1,10 @@
|
||||
# 深入 Kotlin
|
||||
|
||||
|
||||
## 接下来可以看
|
||||
|
||||
[目录](../README.md)
|
||||
|
||||
[下一篇:Kotlin Springboot](./Kotlin-Springboot.md)
|
||||
|
||||
[进入 KMP](./进入KMP.md)
|
||||
@@ -0,0 +1 @@
|
||||
# 第一个KMP应用
|
||||
+138
-2
@@ -1,8 +1,144 @@
|
||||
# 进入KMP
|
||||
# 进入 KMP
|
||||
|
||||
> Kotlin Multiplatform 是基于 Jetpack Compose 框架的多平台应用编译技术,目前支持 Android,所有 JVM 平台,IOS,JS 网页(已被抛弃),WASM 网页。
|
||||
|
||||
## 选择一个 IDE
|
||||
|
||||
这可能感觉上很怪,但是 **Android Stuidio 对KMP的支持确实是最好的**。
|
||||
如果你不想做 Android 的部分,用 IDEA 也影响不大,而且 IDEA 有官方中文,Android Stuidio 没有。
|
||||
如果你不想做 Android 的部分,用 IDEA 也影响不大,而且 IDEA 有官方中文,而 Android Stuidio 没有。
|
||||
|
||||
## 项目的基本结构
|
||||
|
||||
一般来讲,一个 KMP 项目在生成的时候,长这样
|
||||
|
||||
- 项目根目录/
|
||||
- androidApp/
|
||||
- desktopApp/
|
||||
- iosApp/
|
||||
- webApp/ (JS 已经死了,现在向我们走来的是 WASM)
|
||||
- shared/
|
||||
- src/
|
||||
- commonMain/
|
||||
- commonTest/
|
||||
- androidMain/
|
||||
- ......
|
||||
- build.gradle.kts
|
||||
- .gitignore
|
||||
- README.md
|
||||
- gradlew (二进制脚本,一个bat,一个sh)
|
||||
- gradle.proporties
|
||||
- local.proporties (默认被 ignore)
|
||||
- build.gradle.kts
|
||||
- settings.gradle.kts
|
||||
|
||||
如果你的项目还要包含 server 的部分的话,那会稍微复杂一点点。
|
||||
|
||||
### 各部分用途
|
||||
|
||||
所有的共享的部分(如UI,基础逻辑)都写在 `shared/commonMain` 里面,不同平台如果要做不同的效果,那么,相应的代码写在对应的 `Main` 里面,`App` 目录主要控制打包设置和进入软件的窗口设定,虽然可以写针对不同平台的不同效果,但是不推荐。
|
||||
|
||||
### 控制依赖与版本
|
||||
|
||||
- `build.gradle.kts` 不要动他就好了
|
||||
- `settings.gradle.kts` 可以设置 Maven 镜像之类
|
||||
- `shared/build.gradle.kts` 用于控制各个部分会用到的依赖和基本编译选项
|
||||
- `androidApp/build.gradle.kts` 用于控制 Android 应用编译时的选项
|
||||
- `desktopApp/build.gradle.kts` 用于控制 desktop 应用编译时的选项
|
||||
- ......
|
||||
|
||||
## 基本的 UI 结构
|
||||
|
||||
KMP 的 UI 以 `@Composable` 函数为核心,各个平台的 `main()` 函数入口都会默认调用 `shared/commonMain/kotlin` 中的 `App()` 函数。基本的 UI 也都会在 commonMain 中编写。
|
||||
|
||||
### @Composable 函数
|
||||
|
||||
我们先讲 `@Composable`,它是一个注解,用于函数或 lambda 变量:
|
||||
|
||||
```kotlin
|
||||
@Composable
|
||||
fun MyButton(a: Int) {
|
||||
TODO() // Composable 函数推荐大写首字母
|
||||
}
|
||||
|
||||
val myCard = @Composable { a: Int ->
|
||||
TODO() // lambda 不推荐
|
||||
} // 变量类型是 @Composable (Int) -> Unit
|
||||
```
|
||||
|
||||
它有几个重要的特点:
|
||||
|
||||
- Composable 函数只能在 main 函数或 Composable 函数中被调用。
|
||||
- 当 Composable 函数的参数发生变化时,它会被立刻重组(重新触发),受影响的 UI 立刻重新绘制。
|
||||
- 如果 Composable 函数的 lambda 参数的函数体中出现了 `Compose state` 对象,那么,当它的状态变化时,函数也会被重组。
|
||||
|
||||
### 保护变量值
|
||||
|
||||
当 Composable 函数被重新触发时,函数中定义的变量值也会重新被定义,这是很不好的,尤其是当我们需要保留变量值的时候。这里,我们有两种方法:
|
||||
|
||||
1. 使用 remember 定义变量,使其变成状态对象。函数重组时,新的变量会保留重组前的值。
|
||||
|
||||
```kotlin
|
||||
@Composable
|
||||
def Counter() {
|
||||
// 每次重组时,randomId 不会被重新生成,始终保留第一次的值
|
||||
val randomId = remember { UUID.randomUUID().toString() }
|
||||
// 如果是可变变量,常使用委托,这里,它是一个枚举类
|
||||
var currentScreen by remember { mutableStateOf(Screens.Home) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
def UserProfile(userId: String) {
|
||||
// 只有当 userId 发生变化时,remember 才会重新计算并更新 userCache
|
||||
val userCache = remember(userId) {
|
||||
fetchUserCacheFromDb(userId)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. 在上一层函数中定义变量,然后把`变量`和`用于修改变量的 lambda 变量`一并传进下一个函数。
|
||||
|
||||
```kotlin
|
||||
// 1. 父级函数:持有状态并定义修改逻辑
|
||||
@Composable
|
||||
fun ParentScreen() {
|
||||
var count by remember { mutableStateOf(0) }
|
||||
|
||||
CounterDisplay(
|
||||
count = count, // 将变量和对应的 Lambda 传入子函数
|
||||
onIncrement = { count++ } // 用于修改变量的 lambda 变量定义于此
|
||||
)
|
||||
}
|
||||
|
||||
// 2. 子级函数:无状态组件(Stateless)
|
||||
@Composable
|
||||
fun CounterDisplay(
|
||||
count: Int, // 传入变量值
|
||||
onIncrement: () -> Unit // 配套的 Lambda
|
||||
) {
|
||||
Button(onClick = onIncrement) {
|
||||
Text("当前点击次数: $count")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 引发重组
|
||||
|
||||
一般来讲就是利用改变参数的值和改变 lambda 中的 Compose state 状态来触发。利用参数变化并没有很常见。
|
||||
|
||||
```kotlin
|
||||
@Composable
|
||||
def Counter() {
|
||||
// 使用 remember + mutableStateOf 保持状态并在值变化时触发重组
|
||||
var count by remember { mutableStateOf(0) }
|
||||
|
||||
Button(onClick = { count++ }) {
|
||||
Text("点击次数: $count")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 接下来可以看
|
||||
|
||||
[目录](../README.md)
|
||||
|
||||
[下一篇:第一个 KMP 应用](./第一个KMP应用.md)
|
||||
@@ -5,12 +5,14 @@
|
||||
### 引入 Kotlin
|
||||
|
||||
1. [引入 Kotlin](Learning/引入Kotlin.md)
|
||||
2.
|
||||
2. [深入 Kotlin](Learning/深入Kotlin.md)
|
||||
3. [Kotlin Springboot](Learning/Kotlin-Springboot.md)
|
||||
4.
|
||||
|
||||
### Kotlin Multiplatform
|
||||
|
||||
1. [基本的项目结构](Learning/基本的项目结构.md)
|
||||
2. [基本的 UI 结构](Learning/基本的UI结构.md)
|
||||
1. [进入 KMP](learning/进入KMP.md)
|
||||
2. [第一个 KMP 应用](Learning/第一个KMP应用.md)
|
||||
3.
|
||||
|
||||
### 番外
|
||||
@@ -20,6 +22,4 @@
|
||||
|
||||
## 有关 KMP 的项目结构
|
||||
|
||||
KMP的项目结构一直在变化,但好在公用代码的目录一直是`commonMain`,如果没有特别的说明,那么我就是在说`shared/src/commonMain`的事。
|
||||
|
||||
|
||||
KMP 的项目结构一直在变化,但好在公用代码的目录一直是 `commonMain`,如果没有特别的说明,那么我就是在说 `shared/src/commonMain` 的事。
|
||||
|
||||
Reference in New Issue
Block a user