Skip to content

Commit f1f469f

Browse files
author
Kuzmin
committed
Merge branch 'docusaurus' into update-university
# Conflicts: # learning/links.md # learning/socket.md
2 parents 053360d + b153c6b commit f1f469f

10 files changed

Lines changed: 377 additions & 113 deletions

File tree

learning/code.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ sidebar_position: 24
66

77
## Приложения
88
* [JetBrains/kotlinconf-app](https://github.com/JetBrains/kotlinconf-app) - official KotlinConf application - backend, android, ios with shared code;
9-
* [Kotlin/mpp-example](https://github.com/Kotlin/mpp-example) - official Multiplatform (android + ios) sample from JetBrains;
9+
* [Kotlin/kmp-basic-sample](https://github.com/Kotlin/kmp-basic-sample) - official Multiplatform (android + ios) sample from JetBrains;
1010
* [JetBrains/KotlinFinder](https://github.com/JetBrains/KotlinFinder) - official KotlinFinder application from JetBrains and IceRock for KotlinConf 2019 (android + ios)
1111
* [touchlab/DroidconKotlin](https://github.com/touchlab/DroidconKotlin) - DroidCon conference application from TouchLab (android + ios);
1212
* [SimonSchubert/Newsout](https://github.com/SimonSchubert/Newsout) - News application sample (android + ios) using database;
@@ -34,5 +34,5 @@ sidebar_position: 24
3434

3535
## Библиотеки
3636
* <https://libs.kmp.icerock.dev>
37-
* <https://www.kamp.ml>
37+
* <https://klibs.io> — каталог KMP библиотек от JetBrains
3838
* [AAkira/Kotlin-Multiplatform-Libraries](https://github.com/AAkira/Kotlin-Multiplatform-Libraries)

learning/kotlin/compiler-plugins.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# Плагины компилятора
22

3-
Компилятор Kotlin позволяет делать модификацию логики компиляции за счет подключения компиляторных
4-
плагинов. На данный момент Kotlin/JVM и Kotlin/JS используют один вариант компиляторных плагинов, а
5-
Kotlin/Native другой. Для подключения используется специальный gradle плагин, который сообщает
6-
компилятору откуда и какие плагины компилятора нужно взять.
3+
Компилятор Kotlin позволяет модифицировать логику компиляции за счёт подключения компиляторных
4+
плагинов. Начиная с Kotlin 1.9+ / 2.0 JVM, JS и Native используют единую IR-инфраструктуру
5+
для плагинов. Для подключения используется специальный Gradle-плагин, который сообщает
6+
компилятору, откуда и какие плагины компилятора нужно взять.
77

88
## Примеры
99

1010
- https://github.com/Foso/KotlinCompilerPluginExample
11-
- https://github.com/Foso/MpApt
12-
- https://github.com/icerockdev/moko-widgets/tree/master/plugin
11+
- https://github.com/Foso/MpApt (архивирован, вместо него рекомендуется KSP)
12+
- https://github.com/icerockdev/moko-widgets/tree/master/plugin (архивирован)
1313
- https://github.com/AhmedMourad0/no-copy
1414
- https://kotlinlang.org/docs/all-open-plugin.html
1515

@@ -33,7 +33,7 @@ kotlin.daemon.jvm.options=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,
3333

3434
## Ссылки
3535

36-
- https://bnorm.medium.com/writing-your-second-kotlin-compiler-plugin-part-1-project-setup-7b05c7d93f6c (6 частей у статьи)
36+
- https://blog.bnorm.dev/writing-your-second-compiler-plugin-part-1 (статья из 6 частей)
3737
- https://medium.com/@heyitsmohit/writing-kotlin-compiler-plugin-with-arrow-meta-cf7b3689aa3e
38-
- https://www.youtube.com/watch?v=w-GMlaziIyo
38+
- https://www.youtube.com/watch?v=w-GMlaziIyo — KotlinConf 2018, Kevin Most «Writing Your First Kotlin Compiler Plugin»
3939
- https://github.com/ShikaSD/kotlin-compiler-notes

learning/kotlin/kotlin-init-cases.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Порядок инициализации при создании объекта класса
44

5-
1. Объявление свойств, указанных в конструкторе класса и присвоение им значений;
5+
1. Объявление свойств, указанных в конструкторе класса, и присвоение им значений;
66
2. Инициализация свойств в теле класса;
77
3. Выполнение кода в блоке init
88
*если свойств в теле класса и блоков init объявлено несколько, они инициализируются в том же порядке, в каком были объявлены*
@@ -32,7 +32,7 @@ class Person(val name: String) {
3232

3333
## Порядок инициализации вложенных и внутренних классов
3434

35-
Вложенные классы не имеют доступа к переменным внешнего класса. При создании экземпляра вложенного класса экземпляр внешнего класса (в котором объявлен вложенный), создан не будет.
35+
Вложенные классы не имеют доступа к переменным внешнего класса. При создании экземпляра вложенного класса экземпляр внешнего класса (в котором объявлен вложенный) создан не будет.
3636

3737
Экземпляр внутреннего класса всегда хранит ссылку на экземпляр внешнего класса. Вначале создается экземпляр внешнего класса, а затем на его основе - экземпляр внутреннего класса
3838

@@ -102,7 +102,7 @@ class Person {
102102
Как и в предыдущем случае, компилятор не подсветит ошибку
103103

104104
````kotlin
105-
object {
105+
val obj = object {
106106
val string: String
107107

108108
init {
@@ -180,7 +180,7 @@ Bounds(x = 1.0, y = 2.0, width = 0.0, height = 0.0)
180180
Bounds(x = 1.0, y = 2.0, width = 3.0, height = 4.0)
181181
````
182182

183-
При создании класса **Player** вначале происходит инициализация его класса-родителя GameObject, внутри которого создается объект класса **Bounds**. К моменту инициализации класса **Player** свойство **bounds** внутри класса-родителя уже проинициализировано значениями: x=1, y=2, которые были переданы в параметры конструктора **Player** и значениями ширины и высоты из родителя **GameObject** width=0.0, height=0.0
183+
При создании класса **Player** вначале происходит инициализация его класса-родителя GameObject, внутри которого создается объект класса **Bounds**. К моменту инициализации класса **Player** свойство **bounds** внутри класса-родителя уже проинициализировано значениями: x=1, y=2, которые были переданы в параметры конструктора **Player**, и значениями ширины и высоты из родителя **GameObject** width=0.0, height=0.0
184184

185185
## Кейс, иллюстрирующий приоритет выполнения блока init перед вторичным конструктором
186186

@@ -215,13 +215,13 @@ println(case.result)
215215
Вернемся к иллюстрации:
216216
[алгоритм](./init_algorhitm.png)
217217

218-
В процессе инициализации при создании экземпляра класса **ClassWithSecondaryConstructor** после вызова вторичного конструктора будет вызван основной конструктор класса + произойдет выполнение кода в его блоке *init* перед выполнением кода в теле вторичного конструктора. Такми образом, этот код
218+
В процессе инициализации при создании экземпляра класса **ClassWithSecondaryConstructor** после вызова вторичного конструктора будет вызван основной конструктор класса + произойдет выполнение кода в его блоке *init* перед выполнением кода в теле вторичного конструктора. Таким образом, этот код
219219

220220
````kotlin
221221
result += "not "
222222
````
223223

224-
будет выполнен перед конкатенацией значений, переданных в параметры вторичного констуктора
224+
будет выполнен перед конкатенацией значений, переданных в параметры вторичного конструктора
225225

226226
````kotlin
227227
this.result += secondValue
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 4
2+
sidebar_position: 6
33
---
44

55
# moko-units

learning/libraries/moko/moko-mvvm.md

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,134 @@ sidebar_position: 3
44

55
# moko-mvvm
66

7-
Библиотека [moko-mvvm](https://github.com/icerockdev/moko-mvvm) позволяет реализовывать приложения с паттерном
8-
Model - View - ViewModel с ViewModel в общем коде.
7+
Библиотека [moko-mvvm](https://github.com/icerockdev/moko-mvvm) предоставляет архитектурные компоненты Model-View-ViewModel для Kotlin Multiplatform. ViewModel работает в общем коде, на Android обеспечивается lifecycle-aware поведение через интеграцию с `androidx.lifecycle`.
8+
9+
## Возможности
10+
11+
- **ViewModel** — хранение и управление UI и данными с `viewModelScope` (CoroutineScope, отменяемый в `onCleared`)
12+
- **LiveData / Flow** — реактивные обёртки с операторами (`map`, `merge`, `combine`, `all`)
13+
- **EventsDispatcher** — отправка одноразовых событий из ViewModel во View с контролем lifecycle (устаревший подход)
14+
- **CFlow / CStateFlow / CMutableStateFlow** — обёртки над корутинными Flow, совместимые со Swift
15+
- **ResourceState** — sealed class для состояний: `Loading`, `Success`, `Empty`, `Failed`
16+
- **Compose Multiplatform / SwiftUI** — готовая интеграция
17+
18+
## Требования
19+
20+
- Android API 16+
21+
- iOS 11.0+
22+
- Gradle 6.8+
23+
24+
## Подключение
25+
26+
```kotlin
27+
// shared/build.gradle.kts
28+
dependencies {
29+
commonMainApi("dev.icerock.moko:mvvm-core:0.16.1")
30+
commonMainApi("dev.icerock.moko:mvvm-flow:0.16.1")
31+
commonMainApi("dev.icerock.moko:mvvm-state:0.16.1")
32+
33+
// Compose Multiplatform
34+
commonMainApi("dev.icerock.moko:mvvm-compose:0.16.1")
35+
commonMainApi("dev.icerock.moko:mvvm-flow-compose:0.16.1")
36+
37+
commonTestImplementation("dev.icerock.moko:mvvm-test:0.16.1")
38+
}
39+
```
40+
41+
Экспорт в iOS framework:
42+
43+
```kotlin
44+
kotlin {
45+
targets.withType(KotlinNativeTarget::class.java).all {
46+
binaries.withType(Framework::class.java).all {
47+
export("dev.icerock.moko:mvvm-core:0.16.1")
48+
export("dev.icerock.moko:mvvm-flow:0.16.1")
49+
}
50+
}
51+
}
52+
```
53+
54+
## Simple ViewModel — счётчик на CStateFlow
55+
56+
```kotlin
57+
// commonMain
58+
class SimpleViewModel : ViewModel() {
59+
private val _counter = MutableStateFlow(0)
60+
val counter: CStateFlow<String> =
61+
_counter.map { it.toString() }
62+
.stateIn(viewModelScope, SharingStarted.Lazily, "0")
63+
.cStateFlow()
64+
65+
fun onCounterButtonPressed() {
66+
_counter.value++
67+
}
68+
}
69+
```
70+
71+
**Compose:**
72+
73+
```kotlin
74+
@Composable
75+
fun CounterScreen(
76+
viewModel: SimpleViewModel = getViewModel(
77+
factory = createViewModelFactory { SimpleViewModel() }
78+
)
79+
) {
80+
val counter: String by viewModel.counter.collectAsState()
81+
82+
Column {
83+
Text(text = counter)
84+
Button(onClick = { viewModel.onCounterButtonPressed() }) {
85+
Text("Press me")
86+
}
87+
}
88+
}
89+
```
90+
91+
**SwiftUI:**
92+
93+
```swift
94+
struct CounterView: View {
95+
@ObservedObject var viewModel: SimpleViewModel = SimpleViewModel()
96+
97+
var body: some View {
98+
VStack {
99+
Text(viewModel.counter.state(\.counter))
100+
Button("Press me") { viewModel.onCounterButtonPressed() }
101+
}
102+
}
103+
}
104+
```
105+
106+
## ResourceState
107+
108+
```kotlin
109+
sealed class ResourceState<out T, out E> {
110+
class Loading<out T, out E> : ResourceState<T, E>()
111+
data class Success<out T, out E>(val data: T) : ResourceState<T, E>()
112+
class Empty<out T, out E> : ResourceState<T, E>()
113+
data class Failed<out T, out E>(val error: E) : ResourceState<T, E>()
114+
}
115+
```
116+
117+
```kotlin
118+
val state: CStateFlow<ResourceState<List<Book>, StringDesc>> = ...
119+
120+
// Compose
121+
when (val s = state.collectAsState().value) {
122+
is ResourceState.Loading -> LoadingState()
123+
is ResourceState.Success -> BookList(s.data)
124+
is ResourceState.Empty -> EmptyState()
125+
is ResourceState.Failed -> ErrorState(s.error)
126+
}
127+
```
128+
129+
## Дополнительный материал
9130

10131
<iframe src="//www.youtube.com/embed/qe8FcIQEmyA?list=PL6yFiPOVXVUi90sQ66dtmuXP-1-TeHwl5" frameborder="0" allowfullscreen width="675" height="380"></iframe>
11132
<br/>
12133
<br/>
134+
135+
- [Референс библиотеки](https://github.com/icerockdev/moko-mvvm)
136+
- [Семплы (DataBinding)](https://github.com/icerockdev/moko-mvvm/tree/master/sample)
137+
- [Семплы (Compose + SwiftUI)](https://github.com/icerockdev/moko-mvvm/tree/master/sample-declarative-ui)

0 commit comments

Comments
 (0)