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
Repository with Store4 [ja]
Search
Daichi Furiya (Wasabeef)
January 17, 2020
Technology
1.6k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Repository with Store4 [ja]
Daichi Furiya (Wasabeef)
January 17, 2020
More Decks by Daichi Furiya (Wasabeef)
See All by Daichi Furiya (Wasabeef)
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
6
2.9k
About Flutter Architecture
wasabeef
1
320
2023 Flutter/Dart Summary
wasabeef
0
140
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
240
I/O Extended 2023 - Flutter 活用事例
wasabeef
10
3.1k
What it Takes to be a Flutter Developer
wasabeef
0
260
FlutterKaigi 2022 Keynote
wasabeef
1
730
Flutter Hooks を使ったアプリ開発 / App Development with the Flutter Hooks
wasabeef
2
1.5k
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
wasabeef
4
2.2k
Other Decks in Technology
See All in Technology
モダンフロントエンド 開発研修
recruitengineers
PRO
4
610
AIエージェントを前提としたプラットフォーム エンジニアリング:GKEで作るAgent-Ready Golden Path
legalontechnologies
PRO
2
220
PLATEAU で バーチャル花火大会
tatsuya1970
0
150
日本語を汚染するAI
route250
1
120
Flutterをカメラで動かしたかった話
sony
1
140
ブラウザ研修 2026
recruitengineers
PRO
6
950
ボトムアップ文化が強い組織で セキュリティをどう根付かせていくかの現在進行形の話 / Making Security Stick in a Bottom-Up Organization
yamaguchitk333
0
210
強化学習「理論」入門
enakai00
3
3.6k
Genie Codeハンズオン基礎編
taka_aki
1
110
第3回しろおびセキュリティスポンサーセッション
log0417
0
170
老害フォレンジッカーはAI羊の夢を見るか?
tadmaddad
0
320
その“隠したつもり”が命取り ── 自前と平文をやめて「正解」に委ねる
kuroneko13
0
110
Featured
See All Featured
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
480
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
570
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.7k
Facilitating Awesome Meetings
lara
57
7.1k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
480
Paper Plane (Part 1)
katiecoart
PRO
1
10k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
490
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
160
Become a Pro
speakerdeck
PRO
31
6.2k
Visualization
eitanlees
152
17k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.7k
Transcript
Repository pattern with Store4 Wasabeef #shibuya_apk
About me Daichi Furiya (降矢 大地) Google Developers Expert CATS,
CyberAgent @wasabeef_jp wasabeef
Repository pattern with Store4
STORE4 - MIGRATING A LIBRARY FROM RXJAVA TO COROUTINES https://kotlinconf.com/talks/video/2019/126904/
そして、MVVM で設 計する上で、使いや すいライブラリが Jetpack には多く存 在します。 Architecture(MVVM) Activity/Fragment Repository
ViewModel LiveData Local Source Room Remote Data Source Retrofit/okHttp https://developer.android.com/jetpack/docs/guide LiveData https://developer.android.com/jetpack/docs/guide https://developer.android.com/jetpack/docs/guide Jetpack
そして、MVVM で設 計する上で、使いや すいライブラリが Jetpack には多く存 在します。 Architecture(MVVM) Activity/Fragment Repository
ViewModel LiveData Local Source Room Remote Data Source Retrofit/okHttp https://developer.android.com/jetpack/docs/guide LiveData https://developer.android.com/jetpack/docs/guide https://developer.android.com/jetpack/docs/guide Jetpack
そして、MVVM で設 計する上で、使いや すいライブラリが Jetpack には多く存 在します。 Architecture(MVVM) Activity/Fragment Repository
ViewModel LiveData Local Source Room Remote Data Source Retrofit/okHttp https://developer.android.com/jetpack/docs/guide LiveData https://developer.android.com/jetpack/docs/guide https://developer.android.com/jetpack/docs/guide Jetpack
そして、MVVM で設 計する上で、使いや すいライブラリが Jetpack には多く存 在します。 Architecture(MVVM) Activity/Fragment Repository
ViewModel LiveData Local Source Room Remote Data Source Retrofit/okHttp https://developer.android.com/jetpack/docs/guide LiveData https://developer.android.com/jetpack/docs/guide https://developer.android.com/jetpack/docs/guide Jetpack Jetpack Jetpack
ただ、Repository の実装については参 考にできるもの (iosched, plaid) はあれど Jetpack で はライブラリ化され ていません。
Architecture(MVVM) Activity/Fragment Repository ViewModel LiveData Local Source Room Remote Data Source Retrofit/okHttp https://developer.android.com/jetpack/docs/guide LiveData https://developer.android.com/jetpack/docs/guide https://developer.android.com/jetpack/docs/guide Jetpack Jetpack Jetpack ?????
Repository pattern? Activity/Fragment Repository ViewModel LiveData Local Source Room Remote
Data Source Retrofit/okHttp https://developer.android.com/jetpack/docs/guide LiveData https://developer.android.com/jetpack/docs/guide https://developer.android.com/jetpack/docs/guide Store4 そこで現在は Dropbox が主体と なって開発されてい る Store4 を使うこ とで、簡単になりそ うなので今回注目し ています。
Repository pattern?
Microsoft によると ...
引用「データソースにアクセス するために必要なロジックをカ プセル化するクラスまたはコン ポーネント。共通のデータアク セス機能を一元化し、保守性を 向上させ、ドメインモデルレイ ヤーからデータベースにアクセ スするために使用されるインフ ラストラクチャまたはテクノロ ジーを分離します。」
Repository pattern? https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design
Android の MVVM に合 わせて要約すると、 Repository を使うこと で、ローカルから取得す るかネットワークから取 得するかを
ViewModel が意識する必要がないよ うにします。 Repository pattern? Activity/Fragment Repository ViewModel LiveData Remote Data Source Retrofit/okHttp Local Source Room https://developer.android.com/jetpack/docs/guide LiveData https://developer.android.com/jetpack/docs/guide https://developer.android.com/jetpack/docs/guide Store4
当たり前のことですが Repository を意識しな くていいのは ViewModel から使う側 の話で、実装において は意識して書かなけれ ばなりません。 Repository
pattern? Activity/Fragment Repository ViewModel LiveData Local Source Room Remote Data Source Retrofit/okHttp https://developer.android.com/jetpack/docs/guide LiveData Store4
Repository pattern? Activity/Fragment Repository ViewModel LiveData Remote Data Source Retrofit/okHttp
https://developer.android.com/jetpack/docs/guide LiveData On Memory Store4 さらにいうと、Local Source が SQLite だけ ではなくその前に On Memory に保存・取得す る仕組みを考えだすと、 実装さらに大変になって いきます。 Local Source Room
よくある課題 ...
例えば、同じ画面に複 数の Fragment がい て、それぞれ User データを取得するため に UserRepository か
ら getUser をコールし たとします。 よくある課題 ... UserRepository#getUser() Activity A Fragment B Fragment C
よくある課題 ... UserRepository#getUser() Activity A Fragment B Fragment C そうすると、
UserRepository がシ ングルトンだとして も、それぞれがネット ワーク通信をして、 データを取得しにいき ます。
もし仮に、User データ がほとんどの場合にお いて短期間で不変な仕 組みであるなら、この ネットワーク通信を し、サーバに負荷をか けるのはもったいない かもしれません。 よくある課題
... UserRepository#getUser() Activity A Fragment B Fragment C
もしこのデータを一定 のルールものキャッ シュする仕組みがあっ たらネットワークの負 荷を減らせるかもしれ ません。 よくある課題 ... UserRepository#getUser() Activity
A Fragment B Fragment C
もしこのデータを一定 のルールものキャッ シュする仕組みがあっ たらネットワークの負 荷を減らせるかもしれ ません。 よくある課題 ... UserRepository#getUser() Activity
A Fragment B Fragment C
Store4 ...?
Store4 ...? dropbox/Store nytimes/Store
build.gradle !// Set the source & target compatibilities to 1.8
android { compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 } !!... } dependencies { !// 2020.1.17 implementation 'com.dropbox.mobile.store:store4:4.0.0-alpha01' }
StoreBuilder typealias UserName = String typealias UserId = String typealias
TimeMs = Long data class User( val id: UserId, val name: UserName, val birthday: TimeMs) val userId: UserId = "wasabeef" UserId を Key として Store で取得するイメージで簡単な説明をしていきます。
StoreBuilder val store = StoreBuilder !!... Repository に相当する Store を
StoreBuilder で実装していきます。 これは、DI で管理することになるかと思います。
StoreBuilder val store = StoreBuilder .fromNonFlow<UserId, User> { key !->
} fromNonFlow<Key, Output> に 最新のデータを取得するためメソッドコールを定義します。
StoreBuilder val store = StoreBuilder .fromNonFlow<UserId, User> { key !->
api.fetchUser(key).user } ここでは、Retrofit など Data source を使って API コールします。
StoreBuilder val store = StoreBuilder .from<UserId, User> { key !->
api.fetchUser(key) } ここでは、Data source が既に Flow 化されているのであれば fromNonFlow {} !-> from {} ͱ͍ͯͩ͘͠͞ɻ
StoreBuilder val store = StoreBuilder .fromNonFlow<UserId, User> { key !->
api.fetchUser(key).user }.persister( reader = !!..., writer = !!..., delete = !!..., ).build() データを永続化するときにどういう振る舞いを行うかを Persister として指定することができます。
StoreBuilder val store = StoreBuilder .fromNonFlow<UserId, User> { key !->
api.fetchUser(key).user }.persister( reader = db.userDao()!::load, writer = db.userDao()!::update, delete = db.userDao()!::clear ).build() もちろん Room で使うことも出来ます。
StoreBuilder val store = StoreBuilder .fromNonFlow<UserId, User> { key !->
api.fetchUser(key).user }.build() 導入初期は Persister を指定しないで、On Memory キャッシュとしてだけ 使うのを試してもいいかもしれません。
suspend fun Store.get(key) !// UserViewModel.kt viewModelScope.launch { userLiveData.value = try
{ val user = store.get("wasabeef") Result.Success(user) } catch(e: Exception) { Result.Error(e) } } StoreBuilder の Store 実装が終わっていれば、get() を使ってデータを取得します。 これは、サスペンド関数なので ViewModel の CoroutineScope 内などで行います。
suspend fun Store.fresh(key) !// UserViewModel.kt viewModelScope.launch { userLiveData.value = try
{ val user = store.fresh("wasabeef") Result.Success(user) } catch(e: Exception) { Result.Error(e) } } fresh() を使ってデータを取得することもできます。
get or fresh ? get(key) 指定されたキーを元にメモリ内または ディスクキャッシュから取得 fresh(key) キャッシュを無視して最新を取得 get
と fresh をどちらを使うかを意識しないといけないのは Repository pattern 概念としては難しいところがあるかもしれませんが … Pull-to-Refresh などの仕組みがある以上、必要なことだと思います。
MemoryPolicy デフォルトのメモリポリシーでは上限 100 個、期限 24 時間となっています。 class MemoryPolicy internal constructor(
val expireAfterWrite: Long, val expireAfterAccess: Long, val expireAfterTimeUnit: TimeUnit, private val maxSizeNotDefault: Long ) { !// expireAfterWrite = TimeUnit.HOURS.toSeconds(24), !// expireAfterTimeUnit = TimeUnit.SECONDS, !// maxSizeNotDefault = 100 }
おしまい..
Image Resources Photos: - https://unsplash.com - https://www.pexels.com - https://www.reddit.com/r/dragonquest/comments/9dm013/ new_desktop_background/
Illustrations: - http://www.chojugiga.com - https://www.irasutoya.com
twitter.com/wasabeef_jp wasabeef.jp github.com/wasabeef