Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Repository with Store4 [ja]
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
340
2023 Flutter/Dart Summary
wasabeef
0
140
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
250
I/O Extended 2023 - Flutter 活用事例
wasabeef
10
3.1k
What it Takes to be a Flutter Developer
wasabeef
0
270
FlutterKaigi 2022 Keynote
wasabeef
1
760
Flutter Hooks を使ったアプリ開発 / App Development with the Flutter Hooks
wasabeef
2
1.6k
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
wasabeef
4
2.3k
Other Decks in Technology
See All in Technology
AI coding 整合正規方法
philipz
0
560
AIは推し活である。
kurazuuuuuu
2
1k
TiDBファミリーにDWHが新登場!! TiDB最新情報 / TiDB update 202609
yoshiakiyamasaki
0
150
手を動かして実感する、Kiro が変える開発体験
inariku
0
410
Kiro Meetup #8 Kiro アップデート (2026/3/21〜2026/9/24)
katzueno
1
300
LT:「このままでいいのかな?」から一歩踏み出した私のデータキャリア選択〜社会人3年目に上京を決意したリアル〜Snowflake女子会 vol.8
snowwmn0824
0
110
AI Native Platform Engineering 〜PlatformとAgileで“作る速さ”を“価値”へ〜
uya116
0
440
ログラスのマルチプロダクトを 支える認証基盤 〜テナントごとに異なる統制とどう向き合うか〜
dada4386
2
190
C#コードの結合を可視化する Roslyn解析による設計改善と リファクタリング判断
dora56
0
970
【ゲームメーカーズスクランブル2026】『Shadowverse: Worlds Beyond』UIとアニメーションで実現する最高のユーザー体験を叶えるプロトタイピング
cygames
PRO
1
700
AI臭い文章とは何なのか
nasuvitz
36
72k
個別開発で終わらせない。 現場の課題をプロダクトの強さに変える StockmarkのFDE
ktkrhr
0
350
Featured
See All Featured
Joys of Absence: A Defence of Solitary Play
codingconduct
1
530
Documentation Writing (for coders)
carmenintech
77
5.5k
The Curious Case for Waylosing
cassininazir
1
540
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
Product Roadmaps are Hard
iamctodd
55
13k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
840
Being A Developer After 40
akosma
91
590k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Navigating Team Friction
lara
192
16k
Typedesign – Prime Four
hannesfritz
42
3.2k
Thoughts on Productivity
jonyablonski
76
5.4k
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