droidkaigi-2018

836437265cbba12ee1b24bbb359a6c15?s=47 Yuya Kaido
February 09, 2018

 droidkaigi-2018

836437265cbba12ee1b24bbb359a6c15?s=128

Yuya Kaido

February 09, 2018
Tweet

Transcript

  1. ϚϧνϩάΠϯͷ࣮૷ํ๏ DroidKaigi 2018 yuyakaido

  2.  ࣗݾ঺հ • yuyakaido • eureka, Inc. • Android Engineer

    • DroidKaigi 2016 • ๻͕ςετ͓͡͞ΜʹͳͬͨܦҢͱ΍ͬͨ͜ͱ • DroidKaigi 2017 • Error Handling in RxJava
  3.  Pairs Japan/Global • ೔ຊ࠷େͷϚονϯάαʔϏε • ୆࿷ɾؖࠃͰ΋αʔϏεల։ • ձһ਺700ສਓ •

    Ϛονϯά਺ɿ5600ສ૊ • Χοϓϧ਺ɿ11ສ૊
  4.  ໨࣍ • ϚϧνϩάΠϯͷఆٛ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • αϯϓϧΞϓϦ

    • ·ͱΊ
  5.  ໨࣍ • ϚϧνϩάΠϯͷఆٛ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • αϯϓϧΞϓϦ

    • ·ͱΊ
  6.  ϚϧνϩάΠϯͷఆٛ • ෳ਺ΞΧ΢ϯτͰಉ࣌ʹϩάΠϯͰ͖Δػೳ

  7.  ϚϧνϩάΠϯͷఆٛ • ෳ਺ΞΧ΢ϯτͰಉ࣌ʹϩάΠϯͰ͖Δػೳ • SNSΞϓϦΛத৺ʹ࣮૷͞Ε͍ͯΔ͜ͱ͕ଟ͍

  8.  ϚϧνϩάΠϯͷఆٛ • ෳ਺ΞΧ΢ϯτͰಉ࣌ʹϩάΠϯͰ͖Δػೳ • SNSΞϓϦΛத৺ʹ࣮૷͞Ε͍ͯΔ͜ͱ͕ଟ͍ • Twitter • Instagram

  9.  ໨࣍ • ϚϧνϩάΠϯͷఆٛ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • αϯϓϧΞϓϦ

    • ·ͱΊ
  10.  ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ผΞΧ΢ϯτͷσʔλ͕දࣔ͞Εͯ͠·͏ • ผΞΧ΢ϯτͷσʔλΛ্ॻ͖ͯ͠͠·͏ • ίʔυ͕ෳࡶԽͯ͠͠·͏

  11.  ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ผΞΧ΢ϯτͷσʔλ͕දࣔ͞Εͯ͠·͏ • άϩʔόϧม਺΍ঢ়ଶΛ࣋ͭγϯάϧτϯ • ผΞΧ΢ϯτͷσʔλΛ্ॻ͖ͯ͠͠·͏ • ίʔυ͕ෳࡶԽͯ͠͠·͏

  12.  ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ผΞΧ΢ϯτͷσʔλ͕දࣔ͞Εͯ͠·͏ • άϩʔόϧม਺΍ঢ়ଶΛ࣋ͭγϯάϧτϯ • ผΞΧ΢ϯτͷσʔλΛ্ॻ͖ͯ͠͠·͏ • σʔλ΍ඇಉظॲཧ͕ΞΧ΢ϯτ୯Ґʹͳ͍ͬͯͳ͍

    • ίʔυ͕ෳࡶԽͯ͠͠·͏
  13.  ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ผΞΧ΢ϯτͷσʔλ͕දࣔ͞Εͯ͠·͏ • άϩʔόϧม਺΍ঢ়ଶΛ࣋ͭγϯάϧτϯ • ผΞΧ΢ϯτͷσʔλΛ্ॻ͖ͯ͠͠·͏ • σʔλ΍ඇಉظॲཧ͕ΞΧ΢ϯτ୯Ґʹͳ͍ͬͯͳ͍

    • ίʔυ͕ෳࡶԽͯ͠͠·͏ • ෳ਺ΞΧ΢ϯτલఏͷΞʔΩςΫνϟʹͳ͍ͬͯͳ͍
  14.  ϚϧνϩάΠϯ࣮૷Λࠔ೉ʹ͢ΔϙΠϯτ • άϩʔόϧม਺΍ঢ়ଶΛ࣋ͭγϯάϧτϯ • σʔλ΍ඇಉظॲཧ͕ΞΧ΢ϯτ୯Ґʹͳ͍ͬͯͳ͍ • ෳ਺ΞΧ΢ϯτલఏͷΞʔΩςΫνϟʹͳ͍ͬͯͳ͍

  15.  άϩʔόϧม਺΍ঢ়ଶΛ࣋ͭγϯάϧτϯ • ผΞΧ΢ϯτͷσʔλ͕දࣔ͞Εͯ͠·͏ • ΞΧ΢ϯτ੾ସ࣌ͷϋϯυϦϯά͕൥ࡶʹͳΔ • ϩάΞ΢τͯ͠΋σʔλ͕࢒ͬͯ͠·͏ Global /

    Singleton Account 1 Account 2
  16.  ΞΧ΢ϯτ୯ҐͰ؅ཧ͞Ε͍ͯͳ͍σʔλ΍ඇಉظॲཧ • ඇಉظॲཧͷ݁ՌΛѻ͏ࡍʹɺͲͷΞΧ΢ϯτͷσʔλ ͳͷ͔Λҙࣝ͢Δඞཁ͕͋Δ • ඇಉظॲཧͷ࣮ߦதʹΞΧ΢ϯτ੾ସ͕ߦΘΕͨ৔߹ɺ ੾Γସ͑ઌͷΞΧ΢ϯτʹӨڹ͕ٴΜͰ͠·͏ Account 1

    API Server Account 2
  17.  ίʔυͷෳࡶԽ • σʔλΛѻ͏౓ʹͲͷΞΧ΢ϯτʹඥ෇͘΋ͷͳͷ͔Λ ҙࣝ͢Δඞཁ͕͋Δ Activity 1 Account 1 Account

    2 Activity 2 Account 1 Account 2
  18.  ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • άϩʔόϧม਺΍ঢ়ଶΛ࣋ͭγϯάϧτϯ • ΞΧ΢ϯτ୯ҐͰ؅ཧ͞Ε͍ͯͳ͍σʔλ΍ඇಉظॲཧ • ίʔυͷෳࡶԽ

  19.  ໨࣍ • ϚϧνϩάΠϯͷఆٛ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • αϯϓϧΞϓϦ

    • ·ͱΊ
  20.  ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • ҰൠతͳΞϓϦ͸ɺActivity - ViewModel - Repositoryͱ ͍ͬͨϨΠϠʔʹͳΔ͜ͱ͕ଟ͍

  21.  ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • ҰൠతͳΞϓϦ͸ɺActivity - ViewModel - Repositoryͱ ͍ͬͨϨΠϠʔʹͳΔ͜ͱ͕ଟ͍ •

    ෳ਺ΞΧ΢ϯτͰಉ࣌ϩάΠϯ͕ඞཁͳΞϓϦͰ͸ɺ RepositoryҎԼΛΞΧ΢ϯτ୯ҐͰ؅ཧ͢Δͱ͍͍
  22.  ҰൠతͳΞʔΩςΫνϟ ViewModel Repository Data Source Activity Application

  23.  ϚϧνϩάΠϯʹదͨ͠ΞʔΩςΫνϟ LoggedInAccount Account Activity Repository Data Source Account Repository

    Data Source Application
  24.  ΞʔΩςΫνϟͷϙΠϯτ • ApplicationͱAccountΛ໌֬ʹ۠ผ͍ͯ͠Δ͜ͱ

  25.  ΞʔΩςΫνϟͷϙΠϯτ • ApplicationͱAccountΛ໌֬ʹ۠ผ͍ͯ͠Δ͜ͱ • Application • ಛఆͷΞΧ΢ϯτʹґଘ͠ͳ͍σʔλ΍ॲཧΛѻ͏ • ΞϓϦશମͷઃఆɺશͯͷΞΧ΢ϯτʹద༻͢Δઃఆ

  26.  ΞʔΩςΫνϟͷϙΠϯτ • ApplicationͱAccountΛ໌֬ʹ۠ผ͍ͯ͠Δ͜ͱ • Application • ಛఆͷΞΧ΢ϯτʹґଘ͠ͳ͍σʔλ΍ॲཧΛѻ͏ • ΞϓϦશମͷઃఆɺશͯͷΞΧ΢ϯτʹద༻͢Δઃఆ

    • Account • ΞΧ΢ϯτʹґଘͨ͠σʔλ΍ॲཧΛѻ͏ • HttpClient/SharedPreference etc…
  27.  Πϯελϯε؅ཧ • ֤ϨΠϠʔͷΠϯελϯε͸ϥΠϑαΠΫϧ͕ҟͳΔ

  28.  Πϯελϯε؅ཧ • ֤ϨΠϠʔͷΠϯελϯε͸ϥΠϑαΠΫϧ͕ҟͳΔ • Application • ΞϓϦىಈʙऴྃ·Ͱ

  29.  Πϯελϯε؅ཧ • ֤ϨΠϠʔͷΠϯελϯε͸ϥΠϑαΠΫϧ͕ҟͳΔ • Application • ΞϓϦىಈʙऴྃ·Ͱ • Account

    • ϩάΠϯʙϩάΞ΢τ·Ͱ
  30.  Πϯελϯε؅ཧ • ֤ϨΠϠʔͷΠϯελϯε͸ϥΠϑαΠΫϧ͕ҟͳΔ • Application • ΞϓϦىಈʙऴྃ·Ͱ • Account

    • ϩάΠϯʙϩάΞ΢τ·Ͱ • ࣗલͰΠϯελϯε؅ཧΛ࣮૷ͯ͠΋͍͍͕ɺDagger ͳͲͷDIίϯςφΛ࢖͏ͱָʹ࣮૷Ͱ͖Δ
  31.  Πϯελϯε؅ཧ • ApplicationScopeɿΞϓϦىಈʙऴྃ·Ͱ • AccountScopeɿϩάΠϯʙϩάΞ΢τ·Ͱ • PresentationScopeɿը໘ىಈʙऴྃ·Ͱ

  32.  ໨࣍ • ϚϧνϩάΠϯͷఆٛ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • αϯϓϧΞϓϦ

    • ·ͱΊ
  33.  αϯϓϧΞϓϦ • ϚϧνϩάΠϯ͕ՄೳͳTwitterΫϥΠΞϯτ • งғؾΛ఻͑ΔͨΊͷϛχϚϜͳαϯϓϧ • https://github.com/yuyakaido/Android-Blueprint

  34.  ΞʔΩςΫνϟ LoggedInAccount Account Activity Repository Preference Data Source Account

    Repository Preference Data Source
  35.  ΞʔΩςΫνϟ LoggedInAccount Account Activity Repository Preference Data Source Account

    Repository Preference Data Source
  36.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  37.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  38.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  39.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  40.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  41.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  42.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  43.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  44.  Account • 1ͭͷΞΧ΢ϯτΛදݱ͢ΔΫϥε • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢Δ class Account(val twitter: TwitterSession)

    { @Inject lateinit var repository: TweetRepository @Inject lateinit var preference: AccountPreference @Inject lateinit var disposables: CompositeDisposable fun onLoggedIn() // ΞΧ΢ϯτͷϩάΠϯॲཧ fun onLoggedOut() // ΞΧ΢ϯτͷϩάΞ΢τॲཧ fun save() // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  45.  ΞʔΩςΫνϟ LoggedInAccount Account Activity Repository Preference Data Source Account

    Repository Preference Data Source
  46.  AccountPreference • ΞΧ΢ϯτݻ༗ͷ৘ใΛอଘ͢ΔͨΊͷΫϥε • SharedPreferenceΛ༻͍࣮ͯ૷ • ΞΧ΢ϯτຖʹϑΝΠϧΛ෼ׂ class AccountPreference

    @Inject constructor( private val preference: SharedPreferences) { fun load(): Account // ΞΧ΢ϯτΛಡΈࠐΉ fun save(account: Account) // ΞΧ΢ϯτΛอଘ͢Δ fun delete() // ΞΧ΢ϯτΛ࡟আ͢Δ }
  47.  ΞʔΩςΫνϟ LoggedInAccount Account Activity Repository Preference Data Source Account

    Repository Preference Data Source
  48.  OkHttpClient • HTTP௨৴Λ͢ΔͨΊͷΫϥε • ೝূ৘ใ͸ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ AccountScopeͰ؅ཧ @Module class AccountModule(private

    val account: Account) { @AccountScope @Provides fun provideOkHttpClient(): OkHttpClient { val consumer = OkHttpOAuthConsumer( BuildConfig.TWITTER_CONSUMER_KEY, BuildConfig.TWITTER_CONSUMER_SECRET) consumer.setTokenWithSecret( account.twitter.authToken.token, account.twitter.authToken.secret) return OkHttpClient.Builder() .addInterceptor(SigningInterceptor(consumer)) .build() } }
  49.  OkHttpClient • HTTP௨৴Λ͢ΔͨΊͷΫϥε • ೝূ৘ใ͸ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ AccountScopeͰ؅ཧ @Module class AccountModule(private

    val account: Account) { @AccountScope @Provides fun provideOkHttpClient(): OkHttpClient { val consumer = OkHttpOAuthConsumer( BuildConfig.TWITTER_CONSUMER_KEY, BuildConfig.TWITTER_CONSUMER_SECRET) consumer.setTokenWithSecret( account.twitter.authToken.token, account.twitter.authToken.secret) return OkHttpClient.Builder() .addInterceptor(SigningInterceptor(consumer)) .build() } }
  50.  OkHttpClient • HTTP௨৴Λ͢ΔͨΊͷΫϥε • ೝূ৘ใ͸ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ AccountScopeͰ؅ཧ @Module class AccountModule(private

    val account: Account) { @AccountScope @Provides fun provideOkHttpClient(): OkHttpClient { val consumer = OkHttpOAuthConsumer( BuildConfig.TWITTER_CONSUMER_KEY, BuildConfig.TWITTER_CONSUMER_SECRET) consumer.setTokenWithSecret( account.twitter.authToken.token, account.twitter.authToken.secret) return OkHttpClient.Builder() .addInterceptor(SigningInterceptor(consumer)) .build() } }
  51.  Retrofit • ΈΜͳେ޷͖Retrofit • OkHttpClient͕ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ Retrofit΋AccountScopeͰ؅ཧ @Module class AccountModule(private

    val account: Account) { @AccountScope @Provides fun provideRetrofit(client: OkHttpClient): Retrofit { return Retrofit.Builder() .baseUrl("https://api.twitter.com/1.1/") .client(client) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build() } }
  52.  Retrofit • ΈΜͳେ޷͖Retrofit • OkHttpClient͕ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ Retrofit΋AccountScopeͰ؅ཧ @Module class AccountModule(private

    val account: Account) { @AccountScope @Provides fun provideRetrofit(client: OkHttpClient): Retrofit { return Retrofit.Builder() .baseUrl("https://api.twitter.com/1.1/") .client(client) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build() } }
  53.  Retrofit • ΈΜͳେ޷͖Retrofit • OkHttpClient͕ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ Retrofit΋AccountScopeͰ؅ཧ @Module class AccountModule(private

    val account: Account) { @AccountScope @Provides fun provideRetrofit(client: OkHttpClient): Retrofit { return Retrofit.Builder() .baseUrl("https://api.twitter.com/1.1/") .client(client) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build() } }
  54.  TwitterClient • Twitter APIΛୟͨ͘ΊͷΫϥε • Retrofit͕ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ TwitterClient΋AccountScopeͰ؅ཧ interface TwitterClient

    { @GET("statuses/user_timeline.json") fun getUserTimeline(): Observable<List<Tweet>> } @Module class AccountModule(private val account: Account) { @AccountScope @Provides fun provideTwitterClient(retrofit: Retrofit): TwitterClient { return retrofit.create(TwitterClient::class.java) } }
  55.  TwitterClient • Twitter APIΛୟͨ͘ΊͷΫϥε • Retrofit͕ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ TwitterClient΋AccountScopeͰ؅ཧ interface TwitterClient

    { @GET("statuses/user_timeline.json") fun getUserTimeline(): Observable<List<Tweet>> } @Module class AccountModule(private val account: Account) { @AccountScope @Provides fun provideTwitterClient(retrofit: Retrofit): TwitterClient { return retrofit.create(TwitterClient::class.java) } }
  56.  TwitterClient • Twitter APIΛୟͨ͘ΊͷΫϥε • Retrofit͕ΞΧ΢ϯτݻ༗ͷ΋ͷͰ͋ΔͨΊɺ TwitterClient΋AccountScopeͰ؅ཧ interface TwitterClient

    { @GET("statuses/user_timeline.json") fun getUserTimeline(): Observable<List<Tweet>> } @Module class AccountModule(private val account: Account) { @AccountScope @Provides fun provideTwitterClient(retrofit: Retrofit): TwitterClient { return retrofit.create(TwitterClient::class.java) } }
  57.  TweetRepository • TweetΛऔಘ͢ΔͨΊͷΫϥε • TwitterClient͕ΞΧ΢ϯτݻ༗ͳ΋ͷͰ͋ΔͨΊɺ AccountScopeͰ؅ཧ @AccountScope class TweetRepository

    @Inject constructor( private val client: TwitterClient) { fun getUserTimeline(): Observable<List<Tweet>> }
  58.  TweetRepository • TweetΛऔಘ͢ΔͨΊͷΫϥε • TwitterClient͕ΞΧ΢ϯτݻ༗ͳ΋ͷͰ͋ΔͨΊɺ AccountScopeͰ؅ཧ @AccountScope class TweetRepository

    @Inject constructor( private val client: TwitterClient) { fun getUserTimeline(): Observable<List<Tweet>> }
  59.  ΞʔΩςΫνϟ LoggedInAccount Account Activity Repository Preference Data Source Account

    Repository Preference Data Source
  60.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  61.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  62.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  63.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  64.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  65.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  66.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  67.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  68.  LoggedInAccount • ϩάΠϯࡁΈΞΧ΢ϯτΛ؅ཧ͢ΔͨΊͷΫϥε class LoggedInAccount @Inject constructor( private val

    application: Application, private val preference: AppPreference) { private val accounts = BehaviorRelay.createDefault( preference.accounts()) private var current = BehaviorRelay.createDefault( Pack(accounts.value.firstOrNull())) fun current(): Observable<Pack<Account?>> // ݱࡏબ୒தͷΞΧ΢ϯτΛฦ٫ fun accounts(): Observable<List<Account>> // ϩάΠϯࡁΈͷΞΧ΢ϯτΛฦ٫ fun switchTo(index: Int) // ΞΧ΢ϯτΛ੾Γସ͑Δ fun add(account: Account) // ΞΧ΢ϯτΛ௥Ճ͢Δ fun remove(account: Account) // ΞΧ΢ϯτΛ࡟আ͢Δ }
  69.  AppPreference • ϩάΠϯࡁΈΞΧ΢ϯτΛอଘ͢ΔΫϥε • SharedPreferenceΛ༻͍࣮ͯ૷ class AppPreference @Inject constructor(

    private val application: Application, private val preference: SharedPreferences) { fun accounts(): List<Account> // ΞΧ΢ϯτϦετΛฦ٫ fun save(account: Account) // ΞΧ΢ϯτΛอଘ fun delete(account: Account) // ΞΧ΢ϯτΛ࡟আ }
  70.  AppPreference • ϩάΠϯࡁΈΞΧ΢ϯτΛอଘ͢ΔΫϥε • SharedPreferenceΛ༻͍࣮ͯ૷ class AppPreference @Inject constructor(

    private val application: Application, private val preference: SharedPreferences) { fun accounts(): List<Account> // ΞΧ΢ϯτϦετΛฦ٫ fun save(account: Account) // ΞΧ΢ϯτΛอଘ fun delete(account: Account) // ΞΧ΢ϯτΛ࡟আ }
  71.  AppPreference • ϩάΠϯࡁΈΞΧ΢ϯτΛอଘ͢ΔΫϥε • SharedPreferenceΛ༻͍࣮ͯ૷ class AppPreference @Inject constructor(

    private val application: Application, private val preference: SharedPreferences) { fun accounts(): List<Account> // ΞΧ΢ϯτϦετΛฦ٫ fun save(account: Account) // ΞΧ΢ϯτΛอଘ fun delete(account: Account) // ΞΧ΢ϯτΛ࡟আ }
  72.  AppPreference • ϩάΠϯࡁΈΞΧ΢ϯτΛอଘ͢ΔΫϥε • SharedPreferenceΛ༻͍࣮ͯ૷ class AppPreference @Inject constructor(

    private val application: Application, private val preference: SharedPreferences) { fun accounts(): List<Account> // ΞΧ΢ϯτϦετΛฦ٫ fun save(account: Account) // ΞΧ΢ϯτΛอଘ fun delete(account: Account) // ΞΧ΢ϯτΛ࡟আ }
  73.  AppPreference • ϩάΠϯࡁΈΞΧ΢ϯτΛอଘ͢ΔΫϥε • SharedPreferenceΛ༻͍࣮ͯ૷ class AppPreference @Inject constructor(

    private val application: Application, private val preference: SharedPreferences) { fun accounts(): List<Account> // ΞΧ΢ϯτϦετΛฦ٫ fun save(account: Account) // ΞΧ΢ϯτΛอଘ fun delete(account: Account) // ΞΧ΢ϯτΛ࡟আ }
  74.  ΞʔΩςΫνϟ LoggedInAccount Account Activity Repository Preference Data Source Account

    Repository Preference Data Source
  75.  έʔεผͷॲཧϑϩʔ • ΞϓϦىಈ • ΞΧ΢ϯτ௥Ճ • ΞΧ΢ϯτ੾Γସ͑ • ΞΧ΢ϯτ࡟আ

  76.  έʔεผͷॲཧϑϩʔ • ΞϓϦىಈ • ΞΧ΢ϯτ௥Ճ • ΞΧ΢ϯτ੾Γସ͑ • ΞΧ΢ϯτ࡟আ

  77.  ΞϓϦىಈ • LoggedInAccount͕AppPreference͔ΒϩάΠϯࡁΈͷ ΞΧ΢ϯτΛ෮ݩ • TimelineActivity͕֘౰ΞΧ΢ϯτͷλΠϜϥΠϯΛදࣔ LoggedInAccount Account 1

    Account 2 TimelineActivity Account 1
  78.  έʔεผͷॲཧϑϩʔ • ΞϓϦىಈ • ΞΧ΢ϯτ௥Ճ • ΞΧ΢ϯτ੾Γସ͑ • ΞΧ΢ϯτ࡟আ

  79.  ΞΧ΢ϯτ௥Ճ • TwitterSession͔ΒAccountΛੜ੒ • AccountΛLoggedInAccountʹ௥Ճ • TimelineActivity͕֘౰ΞΧ΢ϯτͷλΠϜϥΠϯΛදࣔ LoggedInAccount Account

    1 Account 2 TimelineActivity Account 2
  80.  έʔεผͷॲཧϑϩʔ • ΞϓϦىಈ • ΞΧ΢ϯτ௥Ճ • ΞΧ΢ϯτ੾Γସ͑ • ΞΧ΢ϯτ࡟আ

  81.  ΞΧ΢ϯτ੾Γସ͑ • LoggedInAccount͕ΞΧ΢ϯτΛ੾Γସ͑ • TimelineActivity͕֘౰ΞΧ΢ϯτͷλΠϜϥΠϯΛදࣔ LoggedInAccount Account 1 Account

    2 TimelineActivity Account 2 Account 1 Account 2
  82.  έʔεผͷॲཧϑϩʔ • ΞϓϦىಈ • ΞΧ΢ϯτ௥Ճ • ΞΧ΢ϯτ੾Γସ͑ • ΞΧ΢ϯτ࡟আ

  83.  ΞΧ΢ϯτ࡟আ • LoggedInAccount͕֘౰ΞΧ΢ϯτͷ࡟আॲཧΛ࣮ߦ • ඇಉظॲཧͷΩϟϯηϧɺσʔλͷ࡟আ LoggedInAccount Account 1 Account

    2 TimelineActivity Account 2
  84.  ໨࣍ • ϚϧνϩάΠϯͷఆٛ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ϚϧνϩάΠϯ࣮૷ͷઃܭํ਑ • αϯϓϧΞϓϦ

    • ·ͱΊ
  85.  ·ͱΊ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ผΞΧ΢ϯτ΁ͷׯব • ίʔυͷෳࡶԽ

  86.  ·ͱΊ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ผΞΧ΢ϯτ΁ͷׯব • ίʔυͷෳࡶԽ • σʔλΞΫηε΍ඇಉظॲཧΛ൐͏෦෼ΛΞΧ΢ϯτ୯

    ҐͰߏங͢Δ͜ͱͰ҆શ͔ͭγϯϓϧʹ࣮૷Մೳ
  87.  ·ͱΊ • ϚϧνϩάΠϯ࣮૷ͰΑ͋͘Δ໰୊ • ผΞΧ΢ϯτ΁ͷׯব • ίʔυͷෳࡶԽ • σʔλΞΫηε΍ඇಉظॲཧΛ൐͏෦෼ΛΞΧ΢ϯτ୯

    ҐͰߏங͢Δ͜ͱͰ҆શ͔ͭγϯϓϧʹ࣮૷Մೳ • αϯϓϧΞϓϦ • ෳ਺ΞΧ΢ϯτͰϩάΠϯՄೳͳTwitterΫϥΠΞϯτ • ΞΧ΢ϯτ୯ҐͰσʔλ΍ඇಉظॲཧΛ؅ཧ͢ΔͱΠ Πײ͡ʹ
  88.  Thank you :) Credit: NASA Earth Observatory/NOAA NGDC