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
Extension functions for LiveData
Search
Hiroyuki Kusu
August 21, 2020
Programming
520
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Extension functions for LiveData
Yumemi.apk #1 (
https://yumemi.connpass.com/event/180842/
) の資料
Hiroyuki Kusu
August 21, 2020
More Decks by Hiroyuki Kusu
See All by Hiroyuki Kusu
モノレポのプルリクエストに最近、導入したもの
hkusu
2
590
GitHub composite actions
hkusu
2
450
Android の静的解析における SARIF ファイルの活用
hkusu
0
5.6k
CI_でライブラリのバージョンの変化をレポートする.pdf
hkusu
0
420
Maestro を GitHub Actions で動かす 〜Android編〜
hkusu
1
1.8k
Android の CI(GitHub Actions)の改善で、最近やったこと
hkusu
0
740
Tauri Mobile で生成される Android のコードを見てみる
hkusu
0
1.6k
Custom GitHub Actions を作って Organization 内で共有する
hkusu
1
600
GitHub Actions でユニットテストの結果をレポートする
hkusu
0
3.9k
Other Decks in Programming
See All in Programming
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
280
ローカルLLMでどこまでコードが書けるか -縮小版 / How much code can be written on a local LLM Shortened
kishida
2
190
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
800
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
340
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
210
えっ!!コードを読まずに開発を!?
hananouchi
0
220
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
【やさしく解説 設計編 #0】DDDのコード、読めるのに分からない人へ
panda728
PRO
2
270
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
220
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.5k
20260623_Loop Engineeringで自分の分身の問い合わせBotを作る
ryugen04
0
230
Featured
See All Featured
Thoughts on Productivity
jonyablonski
76
5.2k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
220
Being A Developer After 40
akosma
91
590k
How to train your dragon (web standard)
notwaldorf
97
6.7k
The Pragmatic Product Professional
lauravandoore
37
7.4k
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.8k
エンジニアに許された特別な時間の終わり
watany
108
250k
From π to Pie charts
rasagy
0
240
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
500
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
510
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
420
Transcript
Extension functions for LiveData 2020.08.21 YUMEMI.apk #1 Hiroyuki Kusu (
@hkusu_ )
About me
https://speakerdeck.com/hkusu/unit-test-for-viewmodel-and-livedata ࠓճ ↑ ʹ࣌ؒతʹؚΊΔ͜ͱ͕ग़དྷͳ͔ͬͨ
ViewModel தͷ LiveData ͷهड़ private val _liveData1: MutableLiveData<Int> = MutableLiveData()
val liveData1: LiveData<Int> = _liveData1 val liveData2: LiveData<Boolean> = liveData1.map { // ... } "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" • σʔλͷؔ࿈ੑ͕એݴతʹఆٛ͞Ε͍ͯΔͱ͔Γ͍͢ • ͬͱศརʹ͍ͨ͠..! • ࣗલͰ࡞֦ͨ͠ுؔΛɺ͍͔ͭ͘հ͠·͢
fun <T, U> LiveData<T>.coMap( coroutineScope: CoroutineScope, coroutineContext: CoroutineContext = coroutineScope.coroutineContext,
block: suspend (T) -> U ): LiveData<U> { val result = MediatorLiveData<U>() result.addSource(this) { coroutineScope.launch(coroutineContext) { result.postValue(block.invoke(it)) } } return result } ※ switchMap() ͱ livedata {} ΛΈ߹Θͤͯಉ͜͡ͱ͕Ͱ͖·͢ ※ ݱঢ়Ͱ inline fun ʹ͢ΔͱམͪΔ https://github.com/Kotlin/kotlinx.coroutines/issues/ coMap val liveData2: LiveData<List<SampleItem>> = liveData1.coMap(viewModelScope) { it: Int delay(3_000) sampleRepository.getItemList(it) // suspending function } ར༻Πϝʔδ ؔͷఆٛ
val liveData3: LiveData<String> = merge(liveData1, liveData2) { i: Int?, b:
Boolean? -> // ... } inline fun <T1, T2, U> merge( liveData1: LiveData<T1>, liveData2: LiveData<T2>, crossinline block: (T1?, T2?) -> U? ): LiveData<U> { val result = MediatorLiveData<U>() result.addSource(liveData1) { t1 -> block.invoke(t1, liveData2.value)?.takeUnless { it is Unit }?.let { result.value = it } } result.addSource(liveData2) { t2 -> block.invoke(liveData1.value, t2)?.takeUnless { it is Unit }?.let { result.value = it } } return result } merge ར༻Πϝʔδ ؔͷఆٛ (֦ுؔͰͳ͘ී௨ͷؔ) block தͰ LiveDataͷߋ৽ΛΩϟϯηϧͰ͖ΔΑ͏ʹ͢Δҝͷॲஔ (Ωϟϯηϧ͍ͨ͠߹null͘͠Γͳ͠Ͱreturn͢Δ)
val liveData2: LiveData<Int> = liveData1.filter { 100 < it }
inline fun <T> LiveData<T>.filter( crossinline block: (T) -> Boolean ): LiveData<T> { val result = MediatorLiveData<T>() result.addSource(this) { if (block.invoke(it)) { result.value = it } } return result } filter ར༻Πϝʔδ ؔͷఆٛ
val liveData2: LiveData<Int> = liveData1.map { // ... }.coMap(viewModelScope) {
// ... }.map { // ... }.coMap(viewModelScope) { // ... }.filter { // ... } ͭͳ͛ͯॻ͚Δ
͋ΔLiveDataͷมߋΛܖػʹͳʹ͔͠ΒͷॲཧΛ͍͕ͨ͠.. ( LiveData ͷͭͳ͕Γ͚ͩͰ্ख͘ઃܭͰ͖ͳ͍έʔε ) val liveData2: LiveData<Boolean> = liveData1.map
{ } ແ༻ͳ LiveData2 Λఆٛͯ͠ɺLiveData2 ͷ Observer ͕ډͳ͍߹ ͜ͷϒϩοΫ࣮ߦ͞Εͳ͍
val observe = liveData1.map { }.observe() // ... override fun
onCleared() { observe.cancel() } class Observe<T>(private val liveData: LiveData<T>) { private val observer = Observer<T> {} fun start() { liveData.observeForever(observer) } fun cancel() { liveData.removeObserver(observer) } } fun <T> LiveData<T>.observe(): Observe<T> = Observe(this).apply { start() } observe ViewModel ͷഁغ࣌ʹ؍ଌΛऴྃͤ͞Δඞཁ observeForever Λར༻ ͜ͷϒϩοΫͰҙͷॲཧ ؔͷఆٛ ར༻Πϝʔδ
https://gist.github.com/hkusu/b258c4e4ef488ccd8b213586417ffbec ࠓճɺհ֦ͨ͠ுؔgistʹஔ͖·ͨ͠
Thank you ! @hkusu_