Kyash Androidのイースターエッグ実装 / Kyash Android Easter Eggs

35e08efcf39d692f540047fb756eb4e3?s=47 konifar
April 18, 2019

Kyash Androidのイースターエッグ実装 / Kyash Android Easter Eggs

35e08efcf39d692f540047fb756eb4e3?s=128

konifar

April 18, 2019
Tweet

Transcript

  1. Kyash Android ͷ ΠʔελʔΤοά࣮૷ 2019/04/18 (໦) Kyash Meetup #6 Kyash

    Inc. @konifar
  2. @konifar (Yusuke Konishi) • ೖࣾͯ͠1೥4ϲ݄͘Β͍
 http://konifar.hatenablog.com/entry/2019/03/22/222554 • AndroidΞϓϦ։ൃ͕ϝΠϯ • ೖ͙ࣾͯ͢͠ʹ39ΞχϝʔγϣϯΛ࣮૷

  3. None
  4. ΠʔελʔΤοά = ָ͓͠Έػೳ

  5. ࡩΞχϝʔγϣϯ • ࡩͬΆ͍จࣈΛτϦΨʔ
 ʹͯ͠ɺࡩ͕෣͍ࢄΔʂ

  6. http://konifar.hatenablog.com/entry/2018/06/14/173716 ࡩΞχϝʔγϣϯͷ͖͔͚ͬ

  7. ࢭ·Βͳ͍ཉ๬

  8. ࠓ͸ͨͿΜ 7छྨ͘Β͍͋Δ

  9. ΠʔελʔΤοάͷ ίʔυ෦෼ͷ࿩Λ͠·͢

  10. ੲͱࠓͷίʔυͷ࿩

  11. 39Ξχϝʔγϣϯ͚ͩͷࠒ • ཤྺৄࡉը໘ͷViewModelͷҰ෦ʹ͸ͼ͜Δ is39() ϝιου • ౰࣌͸͜Μͳʹָ͠ΜͰ΋Β֦͑ͯு͍ͯ͘͠ͱ͸ࢥͬͯͳ͔ͬͨ

  12. ந৅Խ͢Δ

  13. ΠʔελʔΤοάͷ෼ղ 1. ର৅ͷ৔ॴʹ 2. ৚݅ʹԠͯ͡ 3. Կ͔Λදࣔ͢Δ

  14. 39Ξχϝʔγϣϯͷ৔߹ 1. ର৅ͷ৔ॴʹʢૹۚ׬ྃը໘શମʹʣ 2. ৚݅ʹԠͯ͡ʢ39ԁͩͬͨ৔߹ʹʣ 3. Կ͔Λදࣔ͢ΔʢgifΛදࣔ͢Δʣ

  15. ࡩΞχϝʔγϣϯͷ৔߹ 1. ର৅ͷ৔ॴʹʢཤྺৄࡉը໘શମʹʣ 2. ৚݅ʹԠͯ͡ʢ࠷ޙͷϝοηʔδʹࡩͬΆ͍จࣈ͕ೖ͍ͬͯͨ৔߹ʹʣ 3. Կ͔Λදࣔ͢ΔʢՖͼΒͷը૾Λ߱ΒͤΔʣ

  16. ࠓͷΞϯυϩΠυͷ࣮૷ 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Ϋϥεͱͯ͠੾Γ ग़͍ͯ͠Δ
  17. |--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σΟϨΫτϦΛஔ͍͍ͯΔ
  18. |--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 = ૹۚɾ੥ٻ׬ྃը໘શମ
  19. interface TimelineHeaderEasterEgg { @DrawableRes fun getAnimationDrawableResId(): Int? fun shouldShow(): Boolean

    } • λΠϜϥΠϯৄࡉͷ39ΞχϝʔγϣϯͷΠϯλʔϑΣʔε • Կ΋දࣔ͠ͳ͍έʔεͷͨΊʹɺNullObjectύλʔϯͷΑ͏ͳܗͰ NoTransactionEasterEggΫϥε΋࡞͍ͬͯΔ class NoTransactionEasterEgg : TransactionEasterEgg { override fun getAnimationDrawableResId(): Int? = null override fun shouldShow() = false }
  20. /** * डऔ࣌ͷ39Ξχϝʔγϣϯ */ class ThankYouReceiveTimelineHeaderEasterEgg( val amount: Long )

    : TimelineHeaderEasterEgg { override fun getAnimationDrawableResId() = R.drawable.img_receive_39 override fun shouldShow() = amount == 39L } • 39ԁΛड͚औͬͨ৔߹ͷ࣮૷ • දࣔ৚݅ͱͳΔ shouldShow() ͷςετΛ͔ͬ͠Γॻ͍͍ͯΔ
  21. class SakuraEasterEggKeywordsMatcher : EasterEggKeywordsMatcher { override fun getKeywords() = arrayListOf(

    "͘͞Β", "αΫϥ", "ࡩ", "Ֆݟ", "͸ͳΈ", "ϋφϛ", "ԅ", String(byteArrayOf(-16, -97, -116, -72)) // ࡩͷemoji ) } • ͘͞ΒΞχϝʔγϣϯͷΩʔϫʔυΛఆٛ • JUnitͰParameterized TestΛॻ͘
  22. @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)) } }
  23. 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Λฦ͢
  24. 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 • AnimationDrawableResId͸gifͳͷͰɺGifDrawableΛbindͰ͖ ΔBindingAdapterΛ࡞͍ͬͯΔ
 https://github.com/koral--/android-gif-drawable
  25. ࠓޙͷίʔυͷ࿩

  26. ʮͦ΋ͦ΋αʔόʔαΠ υʹϩδοΫ͋Δ΂͖ ͡Όͳ͍ʁʯ

  27. ʮͦ͏ͩͶʂʂʯ

  28. ࠓޙͷ໺๬ • Android/iOSʹϩδοΫ͕ࢄΒ͹Βͳ͍Α͏ʹαʔ όʔαΠυʹϩδοΫΛدͤΔ = APIԽ • ΞχϝʔγϣϯϑΝΠϧΛΫϥΠΞϯτଆͰ࣋ͨͳ ͍Α͏ʹμ΢ϯϩʔυͷ࢓૊ΈΛ༻ҙ͢Δ =

    Ξϓ ϦαΠζͷ࡟ݮ • ΫϥΠΞϯτͰͷந৅ԽͰ࢓༷͕ݻ·͖ͬͯͨࠓͳ Β΍͍͚ͬͯͦ͏
  29. None
  30. ͍Ζ͍Ζࢼͯ͠܅͚ͩͷ ΠʔελʔΤοάΛ୳ͦ͏ʂ ※ ͪͳΈʹࣗ෼ͷkyash_id͸ konifar ͩΑ

  31. ࠙਌ձͰฉ͍ͯ΋Β͑Ε͹ Ͱ͖Δ͚ͩԿͰ΋࿩͠·͢ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ