Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Get started with Kotlin Multiplatform Mobile
Search
Hiroyuki Kusu
March 05, 2021
Programming
0
520
Get started with Kotlin Multiplatform Mobile
Yumemi.apk #3 (
https://yumemi.connpass.com/event/202135/
) の資料
Hiroyuki Kusu
March 05, 2021
Tweet
Share
More Decks by Hiroyuki Kusu
See All by Hiroyuki Kusu
モノレポのプルリクエストに最近、導入したもの
hkusu
2
510
GitHub composite actions
hkusu
2
350
Android の静的解析における SARIF ファイルの活用
hkusu
0
5k
CI_でライブラリのバージョンの変化をレポートする.pdf
hkusu
0
350
Maestro を GitHub Actions で動かす 〜Android編〜
hkusu
1
1.5k
Android の CI(GitHub Actions)の改善で、最近やったこと
hkusu
0
630
Tauri Mobile で生成される Android のコードを見てみる
hkusu
0
1.4k
Custom GitHub Actions を作って Organization 内で共有する
hkusu
1
530
GitHub Actions でユニットテストの結果をレポートする
hkusu
0
3.5k
Other Decks in Programming
See All in Programming
Composerが「依存解決」のためにどんな工夫をしているか #phpcon
o0h
PRO
1
250
おやつのお供はお決まりですか?@WWDC25 Recap -Japan-\(region).swift
shingangan
0
120
Kotlin エンジニアへ送る:Swift 案件に参加させられる日に備えて~似てるけど色々違う Swift の仕様 / from Kotlin to Swift
lovee
1
260
都市をデータで見るってこういうこと PLATEAU属性情報入門
nokonoko1203
1
610
今ならAmazon ECSのサービス間通信をどう選ぶか / Selection of ECS Interservice Communication 2025
tkikuc
21
3.9k
なぜ適用するか、移行して理解するClean Architecture 〜構造を超えて設計を継承する〜 / Why Apply, Migrate and Understand Clean Architecture - Inherit Design Beyond Structure
seike460
PRO
3
750
ISUCON研修おかわり会 講義スライド
arfes0e2b3c
1
430
ふつうの技術スタックでアート作品を作ってみる
akira888
1
490
ペアプロ × 生成AI 現場での実践と課題について / generative-ai-in-pair-programming
codmoninc
1
16k
A full stack side project webapp all in Kotlin (KotlinConf 2025)
dankim
0
110
猫と暮らす Google Nest Cam生活🐈 / WebRTC with Google Nest Cam
yutailang0119
0
110
Systèmes distribués, pour le meilleur et pour le pire - BreizhCamp 2025 - Conférence
slecache
0
120
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.5k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
138
34k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
RailsConf 2023
tenderlove
30
1.1k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.7k
Making Projects Easy
brettharned
116
6.3k
Code Reviewing Like a Champion
maltzj
524
40k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
950
Writing Fast Ruby
sferik
628
62k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
For a Future-Friendly Web
brad_frost
179
9.8k
Transcript
Get started with Kotlin Multiplatform Mobile 2021.03.05 YUMEMI.apk #3 Hiroyuki
Kusu ( @hkusu_ )
About me
https://blog.jetbrains.com/ja/kotlin/2020/09/kotlin-multiplatform-mobile-goes-alpha-ja/
https://kotlinlang.org/docs/mobile/home.html KMM ͷυΩϡϝϯτ
Android Studio ༻ͷϓϥάΠϯ
৽ن KMM ϓϩδΣΫτ࡞༻ͷςϯϓϨʔτ
KMMϓϩδΣΫτͷܗ͕࡞͞ΕΔ
https://github.com/hkusu/KmmSampleApp ؆୯ͳαϯϓϧΛ࡞ͬͯΈͨ
6TF$BTF 3FQPTJUPSZ "QJ %BUB$MBTT "DUJWJUZ 7JFX.PEFM BOESPJE"QQ JPT"QQ ※ ࠓճݕূͰ͖͍ͯ·ͤΜ
(JU)VC"1* TIBSFE
• ಈ࡞֬ೝͨ͠ϩʔΧϧڥ • Android Studio 4.1.2 • Android Studio Plugin
• Kotlin: 1.4.31-release-Studio4.1-1 • Kotlin Multiplatform Mobile: 0.2.0-release-65-Studio4.1 • ϏϧυπʔϧϥΠϒϥϦͷόʔδϣϯ GitHub ͷίʔυͷํΛΈ͍ͯͩ͘͞
plugins { // ... id("kotlinx-serialization") } kotlin { // ...
sourceSets { val commonMain by getting { dependencies { // ... implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0") implementation("io.ktor:ktor-client-core:1.5.2") implementation("io.ktor:ktor-client-serialization:1.5.2") } } // ... val androidMain by getting { dependencies { // ... implementation("io.ktor:ktor-client-android:1.5.2") } } // ... val iosMain by getting { dependencies { implementation("io.ktor:ktor-client-ios:1.5.2") } } // ... } } build.gradle.kts shared Coroutines + serialization + Ktor ͷಋೖ ※ ਖ਼֬ͳઃఆ GitHub ͷίʔυͷํΛݟ͍ͯͩ͘͞
plugins { // ... id("kotlin-kapt") } kotlin { // ...
sourceSets { // ... val androidMain by getting { dependencies { // ... implementation("com.google.dagger:hilt-android:2.31.2-alpha") // javax.annotation.Generated ͕ݟ͔ͭΒͳ͍Τϥʔ͕ग़ΔͷͰ.. compileOnly("javax.annotation:javax.annotation-api:1.3.2") } } // ... } } // ref: https://www.reddit.com/r/Kotlin/comments/ack2r6/problem_using_kapt_in_a_multiplatform_project/ dependencies { "kapt"("com.google.dagger:hilt-android-compiler:2.31.2-alpha") } build.gradle.kts shared ※ ਖ਼֬ͳઃఆ GitHub ͷίʔυͷํΛݟ͍ͯͩ͘͞ Dagger Hilt ͷಋೖ(Androidͷํʹ͚ͩ)
buildscript { repositories { gradlePluginPortal() jcenter() google() mavenCentral() } dependencies
{ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.30") classpath("com.android.tools.build:gradle:4.1.2") classpath("org.jetbrains.kotlin:kotlin-serialization:1.4.30") classpath("com.google.dagger:hilt-android-gradle-plugin:2.31.2-alpha") } } allprojects { repositories { google() jcenter() mavenCentral() } } ϓϩδΣΫτϧʔτͷ build.gradle.kts
shared/commonMain Ktor ෦Ҏ֎ී௨ͷ Kotlin + Coroutines ͷίʔυͳͷͰ Ktor ෦͚ͩҎ߱Ͱઆ໌ ڞ௨ιʔε෦
internal object Libs { internal val httpClient: HttpClient by lazy
{ HttpClient { install(JsonFeature) { serializer = KotlinxSerializer(json = Json { ignoreUnknownKeys = true }) } } } } shared/commonMain Ktor ͷ HTTP ΫϥΠΞϯτͷੜͱ Kotlin serialization ͷઃఆ Android/iOS Ͱڞ௨ͷઃఆͰOK
internal class GitHubApi(private val httpClient: HttpClient) { suspend fun getUserList():
List<GitHubUserResponse> { return httpClient.get("${BASE_URL}/users") } companion object { private const val BASE_URL = "https://api.github.com" } } shared/commonMain suspending function ʹରԠ APIͷఆٛ
@Module @InstallIn(SingletonComponent::class) internal object Module { @Provides fun provideGitHubApi(): GitHubApi
{ return GitHubApi(Libs.httpClient) } @Provides @Singleton fun provideUserRepository(gitHubApi: GitHubApi): UserRepository { return UserRepositoryImpl(gitHubApi) } @Provides fun provideGetUserUseCase(userRepository: UserRepository): GetUserUseCase { return GetUserUseCase(userRepository) } } shared/androidMain Dagger Hilt ͷϞδϡʔϧ ※ commonMain ʹ Dagger ແ͘ίϯετϥΫλΠϯδΣΫγϣϯͰ͖ͳ͍ͷͰ ͜͜ͰΠϯελϯεੜํ๏Λఆٛ (SharedͷதͷOSผ࣮)
plugins { id("com.android.application") kotlin("android") id("kotlin-kapt") id("dagger.hilt.android.plugin") } dependencies { implementation(project(":shared"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2") implementation("androidx.appcompat:appcompat:1.2.0") implementation("androidx.core:core-ktx:1.3.2") implementation("androidx.activity:activity-ktx:1.2.0") implementation("androidx.fragment:fragment-ktx:1.3.0") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0") implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.3.0") implementation("androidx.constraintlayout:constraintlayout:2.0.4") implementation("com.google.android.material:material:1.3.0") implementation("com.google.dagger:hilt-android:2.31.2-alpha") kapt("com.google.dagger:hilt-android-compiler:2.31.2-alpha") } android { compileSdkVersion(29) // ... build.gradle.kts androidApp ͓ͳ͡ΈͷϥΠϒϥϦୡ
plugins { id("com.android.application") kotlin("android") id("kotlin-kapt") id("dagger.hilt.android.plugin") } dependencies { implementation(project(":shared"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2") implementation("androidx.appcompat:appcompat:1.2.0") implementation("androidx.core:core-ktx:1.3.2") implementation("androidx.activity:activity-ktx:1.2.0") implementation("androidx.fragment:fragment-ktx:1.3.0") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0") implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.3.0") implementation("androidx.constraintlayout:constraintlayout:2.0.4") implementation("com.google.android.material:material:1.3.0") implementation("com.google.dagger:hilt-android:2.31.2-alpha") kapt("com.google.dagger:hilt-android-compiler:2.31.2-alpha") } android { compileSdkVersion(29) // ... build.gradle.kts androidApp Dagger Hilt
@HiltViewModel class MainViewModel @Inject constructor(getUser: GetUserUseCase) : ViewModel() { private
val _userList: MutableLiveData<List<User>> = MutableLiveData() val userList = _userList as LiveData<List<User>> init { viewModelScope.launch { _userList.value = getUser() } } } ViewModel androidApp Dagger Hilt
@HiltViewModel class MainViewModel @Inject constructor(getUser: GetUserUseCase) : ViewModel() { private
val _userList: MutableLiveData<List<User>> = MutableLiveData() val userList = _userList as LiveData<List<User>> init { viewModelScope.launch { _userList.value = getUser() } } } ViewModel androidApp shared ʹஔ͍ͨ UseCase Λ inject
• Android ෦ʹؔͯ͠ී௨ʹ࡞Εͦ͏ • Android ͔ΒݟΕී௨ͷϚϧνϞδϡʔϧߏ • ڞ௨ιʔε෦ʹ͍ͭͯ.. • ϚϧνϓϥοτϑΥʔϜରԠͷϥΠϒϥϦΛར༻͢Δඞཁ͕͋Δ
• ͜͜Λ iOS ͚ʹͲ͏ఏڙ͍͔͕ͯ͘͠ϙΠϯτʹͳΓͦ͏ • iOS ͚ʹ DI ͢ΔͳΒ KOIN Kodein Λར༻ͨ͠ํ͕Αͦ͞͏
Thank you ! @hkusu_