Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Kyash Androidのイースターエッグ実装 / Kyash Android Easter Eggs
konifar
April 18, 2019
Programming
2
680
Kyash Androidのイースターエッグ実装 / Kyash Android Easter Eggs
konifar
April 18, 2019
Tweet
Share
More Decks by konifar
See All by konifar
konifar
3
1.1k
konifar
23
10k
konifar
2
220
konifar
2
630
konifar
5
290
konifar
14
16k
konifar
0
820
konifar
3
660
konifar
8
36k
Other Decks in Programming
See All in Programming
mrtc0
1
250
fei0203018
0
200
ktgrstsh
1
240
jschaedl
2
110
o0h
PRO
3
1.6k
karosuwindam
0
120
syucream
4
1.5k
shinnoki
0
1.1k
patrickjahr
0
130
sh_akira
3
140
tkmnzm
1
250
horie1024
2
260
Featured
See All Featured
danielanewman
202
20k
hursman
108
9.3k
schacon
147
6.7k
searls
204
37k
jnunemaker
PRO
40
4.7k
akmur
252
19k
mthomps
39
2.4k
geoffreycrofte
27
1.1k
dougneiner
119
8k
jmmastey
11
710
hannesfritz
29
980
gr2m
84
11k
Transcript
Kyash Android ͷ ΠʔελʔΤοά࣮ 2019/04/18 () Kyash Meetup #6 Kyash
Inc. @konifar
@konifar (Yusuke Konishi) • ೖࣾͯ͠14ϲ݄͘Β͍ http://konifar.hatenablog.com/entry/2019/03/22/222554 • AndroidΞϓϦ։ൃ͕ϝΠϯ • ೖ͙ࣾͯ͢͠ʹ39ΞχϝʔγϣϯΛ࣮
None
ΠʔελʔΤοά = ָ͓͠Έػೳ
ࡩΞχϝʔγϣϯ • ࡩͬΆ͍จࣈΛτϦΨʔ ʹͯ͠ɺࡩ͕͍ࢄΔʂ
http://konifar.hatenablog.com/entry/2018/06/14/173716 ࡩΞχϝʔγϣϯͷ͖͔͚ͬ
ࢭ·Βͳ͍ཉ
ࠓͨͿΜ 7छྨ͘Β͍͋Δ
ΠʔελʔΤοάͷ ίʔυ෦ͷΛ͠·͢
ੲͱࠓͷίʔυͷ
39Ξχϝʔγϣϯ͚ͩͷࠒ • ཤྺৄࡉը໘ͷViewModelͷҰ෦ʹͼ͜Δ is39() ϝιου • ࣌͜Μͳʹָ͠ΜͰΒ֦͑ͯு͍ͯ͘͠ͱࢥͬͯͳ͔ͬͨ
நԽ͢Δ
ΠʔελʔΤοάͷղ 1. ରͷॴʹ 2. ݅ʹԠͯ͡ 3. Կ͔Λදࣔ͢Δ
39Ξχϝʔγϣϯͷ߹ 1. ରͷॴʹʢૹۚྃը໘શମʹʣ 2. ݅ʹԠͯ͡ʢ39ԁͩͬͨ߹ʹʣ 3. Կ͔Λදࣔ͢ΔʢgifΛදࣔ͢Δʣ
ࡩΞχϝʔγϣϯͷ߹ 1. ରͷॴʹʢཤྺৄࡉը໘શମʹʣ 2. ݅ʹԠͯ͡ʢ࠷ޙͷϝοηʔδʹࡩͬΆ͍จࣈ͕ೖ͍ͬͯͨ߹ʹʣ 3. Կ͔Λදࣔ͢ΔʢՖͼΒͷը૾Λ߱ΒͤΔʣ
ࠓͷΞϯυϩΠυͷ࣮ 7JFX.PEFM 5JNFMJOF)FBEFS &BTUFS&HH'BDUPSZ &BTUFS&HH,FZXPSE .BUDIFS 5JNFMJOF)FBEFS &BTUFS&HH 5JNFMJOF)FBEFS &BTUFS&HH
5JNFMJOF)FBEFS &BTUFS&HH EasterEggΛදࣔ͢ΔViewModel͔Β Factoryܦ༝ͰEasterEggΦϒδΣΫτΛऔ Γग़͢ EasterEggΠϯλʔϑΣʔεΛ࣮ͯ͠ ʰදࣔ݅ʱͱʰදࣔ͢ΔϦιʔεʱΛࢦ ఆ͢Δ දࣔ݅ɺଞͷը໘ͷEasterEggΫϥε ͱڞ௨ͳͷͰɺMatcherΫϥεͱͯ͠Γ ग़͍ͯ͠Δ
|--keywords | |--EasterEggKeywordsMatcher.kt | |-—SakuraEasterEggKeywordsMatcher.kt | |…… |--timeline | |--NoTimelineHeaderEasterEgg.kt
| |--ThankYouReceiveTimelineHeaderEasterEgg.kt | |--TimelineHeaderEasterEgg.kt | |-—TimelineHeaderEasterEggFactory.kt | |…… |--transaction | |--NoTransactionEasterEgg.kt | |--ThankYouSendTransactionEasterEgg.kt | |--TransactionEasterEgg.kt | |--TransactionEasterEggFactory.kt | |…… • UIͷσΟϨΫτϦͷதʹeastereggsσΟϨΫτϦΛஔ͍͍ͯΔ
|--keywords | |--EasterEggKeywordsMatcher.kt | |-—SakuraEasterEggKeywordsMatcher.kt | |…… |--timeline | |--NoTimelineHeaderEasterEgg.kt
| |--ThankYouReceiveTimelineHeaderEasterEgg.kt | |--TimelineHeaderEasterEgg.kt | |-—TimelineHeaderEasterEggFactory.kt | |…… |--transaction | |--NoTransactionEasterEgg.kt | |--ThankYouSendTransactionEasterEgg.kt | |--TransactionEasterEgg.kt | |--TransactionEasterEggFactory.kt | |…… • ʮରͷॴʯ͝ͱʹEasterEggΫϥεͱFactoryΫϥεΛ࡞͍ͬͯΔ • timeline = ཤྺৄࡉը໘্෦ • transaction = ૹۚɾٻྃը໘શମ
interface TimelineHeaderEasterEgg { @DrawableRes fun getAnimationDrawableResId(): Int? fun shouldShow(): Boolean
} • λΠϜϥΠϯৄࡉͷ39ΞχϝʔγϣϯͷΠϯλʔϑΣʔε • Կදࣔ͠ͳ͍έʔεͷͨΊʹɺNullObjectύλʔϯͷΑ͏ͳܗͰ NoTransactionEasterEggΫϥε࡞͍ͬͯΔ class NoTransactionEasterEgg : TransactionEasterEgg { override fun getAnimationDrawableResId(): Int? = null override fun shouldShow() = false }
/** * डऔ࣌ͷ39Ξχϝʔγϣϯ */ class ThankYouReceiveTimelineHeaderEasterEgg( val amount: Long )
: TimelineHeaderEasterEgg { override fun getAnimationDrawableResId() = R.drawable.img_receive_39 override fun shouldShow() = amount == 39L } • 39ԁΛड͚औͬͨ߹ͷ࣮ • දࣔ݅ͱͳΔ shouldShow() ͷςετΛ͔ͬ͠Γॻ͍͍ͯΔ
class SakuraEasterEggKeywordsMatcher : EasterEggKeywordsMatcher { override fun getKeywords() = arrayListOf(
"͘͞Β", "αΫϥ", "ࡩ", "Ֆݟ", "ͳΈ", "ϋφϛ", "ԅ", String(byteArrayOf(-16, -97, -116, -72)) // ࡩͷemoji ) } • ͘͞ΒΞχϝʔγϣϯͷΩʔϫʔυΛఆٛ • JUnitͰParameterized TestΛॻ͘
@RunWith(Parameterized::class) class SakuraEasterEggKeywordsMatcherUnitTest( private val message: String, private val result:
Boolean ) { companion object { @JvmStatic @Parameterized.Parameters fun data(): List<Array<out Any?>> { return listOf( arrayOf("αΫϥ͕͘͞", true), arrayOf("", true), arrayOf("α Ϋϥ", false), …… ) } } @Test fun containsKeyword() { val subject = SakuraEasterEggKeywordsMatcher() assertEquals(result, subject.containsKeyword(message)) } }
class TimelineHeaderEasterEggFactory( val amount: Long, val message: String? ) {
// ద༻͞ΕΔॱʹϦετʹηοτ͍ͯ͠·͢ private val easterEggs = arrayListOf( … // ωλόϨʹͳΔͷͰφΠγϣ ThankYouReceiveTimelineHeaderEasterEgg(amount) ) fun createEasterEgg(): TimelineHeaderEasterEgg { easterEggs.forEach { if (it.shouldShow()) return it } return NoTimelineHeaderEasterEgg() } } • FactoryɺEasterEggͷϦετΛ࣋ͬͯɺ݅ʹԠͯ͡࠷ॳʹද ࣔ݅ʹ߹கͨ͠EasterEggΛฦ͢
val easterEgg = TimelineHeaderEasterEggFactory( amount, message ).createEasterEgg() …
@get:Bindable val headerEasterEggVisible: Boolean get() = easterEgg.shouldShow() @get:Bindable val headerEasterEggDrawable: Int? get() = easterEgg.getAnimationDrawableResId() • ViewModelͰEasterEggΛݩʹDataBindingͷΛܾΊͯBind • AnimationDrawableResIdgifͳͷͰɺGifDrawableΛbindͰ͖ ΔBindingAdapterΛ࡞͍ͬͯΔ https://github.com/koral--/android-gif-drawable
ࠓޙͷίʔυͷ
ʮͦͦαʔόʔαΠ υʹϩδοΫ͋Δ͖ ͡Όͳ͍ʁʯ
ʮͦ͏ͩͶʂʂʯ
ࠓޙͷ • Android/iOSʹϩδοΫ͕ࢄΒΒͳ͍Α͏ʹαʔ όʔαΠυʹϩδοΫΛدͤΔ = APIԽ • ΞχϝʔγϣϯϑΝΠϧΛΫϥΠΞϯτଆͰ࣋ͨͳ ͍Α͏ʹμϯϩʔυͷΈΛ༻ҙ͢Δ =
Ξϓ ϦαΠζͷݮ • ΫϥΠΞϯτͰͷநԽͰ༷͕ݻ·͖ͬͯͨࠓͳ Β͍͚ͬͯͦ͏
None
͍Ζ͍Ζࢼͯ͠܅͚ͩͷ ΠʔελʔΤοάΛ୳ͦ͏ʂ ※ ͪͳΈʹࣗͷkyash_id konifar ͩΑ
࠙ձͰฉ͍ͯΒ͑Ε Ͱ͖Δ͚ͩԿͰ͠·͢ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ