オフラインファースト
Amplify DataStore の独自のアプローチについてさらに理解するために、以下のリソースを参照してください。
オフラインファースト アプリケーション構築の原則をさらに探索し理解するために、Android のオフラインファースト アプリケーション構築ガイドを確認することをお勧めします。
これらの機能がアプリケーションにとって重要であることを理解しており、DataStore は新機能を受け取らなくなりますが、スムーズに移行するために必要なリソースを提供したいと考えています。以下のセクションでは、代替ソリューションについての高レベルな推奨事項を示します。
リモート同期
ローカル ストアを定期的に同期することで、アプリケーションのプライマリ ソースとして機能し、オフラインで実行できる読み取り操作を実現できます。オフライン書き込みを管理することを選択すると、アプリケーションに追加の複雑さが生じるため、各個別モデルに対してこれを処理するかどうかを検討することが重要です。
ライブ同期
AWS AppSync サブスクリプションを活用することで、インターネットに接続している限り、リモート リポジトリへの変更(作成、更新、削除)をリアルタイムで検出できます。以下の関数は、リモートの作成、更新、削除をサブスクライブし、それらの変更を Room データベースに伝播します。これらのサブスクリプションは、アプリケーションがインターネットに再接続するたびに確立する必要があります。
suspend fun startSubscriptions() = supervisorScope { // Subscribe to creates apolloClient.subscription(OnCreateSubscription()).toFlow().onEach { response -> response.data?.onCreatePost?.postDetails?.let { post -> postDao.insert(post.toLocalModel()) } }.launchIn(this)
// Subscribe to updates apolloClient.subscription(OnUpdateSubscription()).toFlow().onEach { response -> response.data?.onUpdatePost?.postDetails?.let { post -> postDao.insert(post.toLocalModel()) } }.launchIn(this)
// Subscribe to deletes apolloClient.subscription(OnDeleteSubscription()).toFlow().onEach { response -> response.data?.onDeletePost?.postDetails?.let { post -> postDao.delete(post.toLocalModel()) } }.launchIn(this)}ローカル キャッシュの更新
アプリケーションがインターネットに再接続するたびに、アプリケーション起動またはネットワーク更新を通じて、ローカル ストアの完全な更新を実行して、見落とした可能性のあるすべての更新を確実に受け取るようにしてください。
suspend fun syncAllPosts() { // Sync all pages of posts until there is no nextToken var nextToken: String? = null do { val query = GetPostsQuery(nextToken = Optional.presentIfNotNull(nextToken)) val response = apolloClient.query(query).execute() response.data?.listPosts?.items?.let { posts -> val mapped = posts.mapNotNull { it?.postDetails?.toLocalModel() } postDao.insertAll(mapped) } nextToken = response.data?.listPosts?.nextToken } while (nextToken != null)}大量のデータを頻繁に同期する場合、AWS AppSync Delta Sync 操作を設定することで、ローカル ストアを更新するのに必要な時間を短縮できます。Delta Sync 機能を設定および実装する方法の詳細については、AWS AppSync Delta Sync ガイドをご覧ください。
ネットワーク ステータスの検出
Android の ConnectivityManager を使用してネットワーク ステータス更新をプロアクティブに検出できます。これにより、ローカル キャッシュを同期し、サブスクリプションを再確立する必要があるシナリオを特定できます。
class NetworkMonitor {
enum class Status { Connected, Disconnected }
fun monitor(context: Context) = callbackFlow { val networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { super.onAvailable(network) trySend(Status.Connected) }
override fun onLost(network: Network) { super.onLost(network) trySend(Status.Disconnected) } }
val networkRequest = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .build()
val connectivityManager = context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager connectivityManager.requestNetwork(networkRequest, networkCallback)
awaitClose { connectivityManager.unregisterNetworkCallback(networkCallback) } }}
class SyncEngine(val networkMonitor: NetworkMonitor) { suspend fun start(context: Context) { networkMonitor.monitor(context).collect { networkStatus -> when (networkStatus) { NetworkMonitor.Status.Connected -> startSync() NetworkMonitor.Status.Disconnected -> stopSync() } } }}オフラインミューテーション
ローカルで行われた変更を別のペンディング ミューテーション テーブルに格納し、後で同期することで、ユーザーがオフラインで作業できるようにします。ペンディング ミューテーション テーブルには、以下を含める必要があります。
- 自動インクリメント プライマリ キー(モデルの通常のプライマリ キーではない)
- ミューテーション タイプの列挙(作成、更新、または削除)
- アクション時のモデルの状態
例として、サンプル Post タイプのペンディング ミューテーションは以下のようになります。
enum class MutationType { Create, Update, Delete}
@Entity(tableName = "post_mutation")data class PostMutationEntity( val postId: String, val type: MutationType, val title: String?, val content: String?, val status: PostStatus?, val rating: Int?, val timestamp: String, @PrimaryKey(autoGenerate = true) val id: Int = 0)ペンディング ミューテーションを適用
これらのペンディング ミューテーションは、アプリケーションに接続がある場合、AWS AppSync に同期できます。ペンディング ミューテーション テーブル エントリを同期する前にアプリに組み込むには、PostEntity と PostMutationEntity の両方のインスタンスをフェッチし、それらを単一のディスプレイ モデルに組み合わせ、AWS AppSync によって処理される前にミューテーションを楽観的に適用できます。
fun PostMutationEntity.applyTo(post: PostEntity) = post.copy( title = title ?: post.title, content = content ?: post.content, status = status ?: post.status, rating = rating ?: post.rating)