ソースを参照

Added caching subscriptions in shared preferences

Vadik Sirekanyan 7 年 前
コミット
87a44948aa

+ 3 - 1
app/src/main/java/me/vadik/knigopis/MainActivity.kt

@@ -32,6 +32,7 @@ import me.vadik.knigopis.common.ResourceProvider
 import me.vadik.knigopis.common.StickyHeaderInterface
 import me.vadik.knigopis.data.AvatarCache
 import me.vadik.knigopis.data.AvatarCacheImpl
+import me.vadik.knigopis.data.SubscriptionRepository
 import me.vadik.knigopis.dialog.DialogFactory
 import me.vadik.knigopis.model.*
 import me.vadik.knigopis.model.CurrentTab.*
@@ -59,6 +60,7 @@ class MainActivity : AppCompatActivity(), Router {
     private val auth by inject<KAuth>()
     private val dialogs by inject<DialogFactory> { mapOf("activity" to this) }
     private val bookRepository by inject<BookRepository>()
+    private val userRepository by inject<SubscriptionRepository>()
     private val resourceProvider by inject<ResourceProvider>()
     private val allBooks = mutableListOf<Book>()
     private val allBookHeaders = mutableListOf<BookHeader>()
@@ -410,7 +412,7 @@ class MainActivity : AppCompatActivity(), Router {
     }
 
     private fun refreshUsersTab() {
-        api.getSubscriptions(auth.getAccessToken())
+        userRepository.getSubscriptions()
             .io2main()
             .showProgressBar()
             .subscribe({ subscriptions ->

+ 9 - 0
app/src/main/java/me/vadik/knigopis/common/CacheKey.kt

@@ -0,0 +1,9 @@
+package me.vadik.knigopis.common
+
+enum class CacheKey {
+
+    PLANNED_BOOKS, FINISHED_BOOKS, SUBSCRIPTIONS;
+
+    val storeValue get() = name.toLowerCase()
+
+}

+ 7 - 7
app/src/main/java/me/vadik/knigopis/common/CommonCache.kt

@@ -7,15 +7,15 @@ import io.reactivex.Completable
 import io.reactivex.Maybe
 import java.lang.reflect.Type
 
-private const val PREFS_NAME = "cache1"
+private const val PREFS_NAME = "cached"
 
 inline fun <reified T> genericType(): Type = object : TypeToken<T>() {}.type
 
 interface CommonCache {
 
-    fun <T> saveToJson(key: String, books: List<T>): Completable
+    fun <T> saveToJson(key: CacheKey, books: List<T>): Completable
 
-    fun <T> getFromJson(key: String, type: Type): Maybe<T>
+    fun <T> getFromJson(key: CacheKey, type: Type): Maybe<T>
 
 }
 
@@ -26,17 +26,17 @@ class CommonCacheImpl(
 
     private val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
 
-    override fun <T> getFromJson(key: String, type: Type): Maybe<T> =
+    override fun <T> getFromJson(key: CacheKey, type: Type): Maybe<T> =
         Maybe.fromCallable {
-            prefs.getString(key, null)?.let { json ->
+            prefs.getString(key.storeValue, null)?.let { json ->
                 gson.fromJson<T>(json, type)
             }
         }
 
-    override fun <T> saveToJson(key: String, books: List<T>): Completable =
+    override fun <T> saveToJson(key: CacheKey, books: List<T>): Completable =
         Completable.fromAction {
             prefs.edit()
-                .putString(key, gson.toJson(books))
+                .putString(key.storeValue, gson.toJson(books))
                 .apply()
         }
 

+ 5 - 7
app/src/main/java/me/vadik/knigopis/data/BookCache.kt

@@ -2,14 +2,12 @@ package me.vadik.knigopis.data
 
 import io.reactivex.Completable
 import io.reactivex.Maybe
+import me.vadik.knigopis.common.CacheKey
 import me.vadik.knigopis.common.CommonCache
 import me.vadik.knigopis.common.genericType
 import me.vadik.knigopis.model.FinishedBook
 import me.vadik.knigopis.model.PlannedBook
 
-private const val PLANNED_KEY = "planned"
-private const val FINISHED_KEY = "finished"
-
 interface BookCache {
 
     fun getPlannedBooks(): Maybe<List<PlannedBook>>
@@ -25,15 +23,15 @@ interface BookCache {
 class BookCacheImpl(private val commonCache: CommonCache) : BookCache {
 
     override fun getPlannedBooks(): Maybe<List<PlannedBook>> =
-        commonCache.getFromJson(PLANNED_KEY, genericType<List<PlannedBook>>())
+        commonCache.getFromJson(CacheKey.PLANNED_BOOKS, genericType<List<PlannedBook>>())
 
     override fun getFinishedBooks(): Maybe<List<FinishedBook>> =
-        commonCache.getFromJson(FINISHED_KEY, genericType<List<FinishedBook>>())
+        commonCache.getFromJson(CacheKey.FINISHED_BOOKS, genericType<List<FinishedBook>>())
 
     override fun savePlannedBooks(planned: List<PlannedBook>): Completable =
-        commonCache.saveToJson(PLANNED_KEY, planned)
+        commonCache.saveToJson(CacheKey.PLANNED_BOOKS, planned)
 
     override fun saveFinishedBooks(finished: List<FinishedBook>): Completable =
-        commonCache.saveToJson(FINISHED_KEY, finished)
+        commonCache.saveToJson(CacheKey.FINISHED_BOOKS, finished)
 
 }

+ 26 - 0
app/src/main/java/me/vadik/knigopis/data/SubscriptionCache.kt

@@ -0,0 +1,26 @@
+package me.vadik.knigopis.data
+
+import io.reactivex.Completable
+import io.reactivex.Maybe
+import me.vadik.knigopis.common.CacheKey
+import me.vadik.knigopis.common.CommonCache
+import me.vadik.knigopis.common.genericType
+import me.vadik.knigopis.model.subscription.Subscription
+
+interface SubscriptionCache {
+
+    fun getSubscriptions(): Maybe<List<Subscription>>
+
+    fun saveSubscriptions(planned: List<Subscription>): Completable
+
+}
+
+class SubscriptionCacheImpl(private val commonCache: CommonCache) : SubscriptionCache {
+
+    override fun getSubscriptions(): Maybe<List<Subscription>> =
+        commonCache.getFromJson(CacheKey.SUBSCRIPTIONS, genericType<List<Subscription>>())
+
+    override fun saveSubscriptions(planned: List<Subscription>): Completable =
+        commonCache.saveToJson(CacheKey.SUBSCRIPTIONS, planned)
+
+}

+ 47 - 0
app/src/main/java/me/vadik/knigopis/data/SubscriptionRepository.kt

@@ -0,0 +1,47 @@
+package me.vadik.knigopis.data
+
+import io.reactivex.Completable
+import io.reactivex.Single
+import me.vadik.knigopis.api.Endpoint
+import me.vadik.knigopis.auth.KAuth
+import me.vadik.knigopis.common.NetworkChecker
+import me.vadik.knigopis.logError
+import me.vadik.knigopis.logWarn
+import me.vadik.knigopis.model.subscription.Subscription
+
+interface SubscriptionRepository {
+
+    fun getSubscriptions(): Single<List<Subscription>>
+
+}
+
+class SubscriptionRepositoryImpl(
+    private val api: Endpoint,
+    private val cache: SubscriptionCache,
+    private val auth: KAuth,
+    private val networkChecker: NetworkChecker
+) : SubscriptionRepository {
+
+    override fun getSubscriptions(): Single<List<Subscription>> =
+        if (networkChecker.isNetworkAvailable()) {
+            getFromNetwork()
+                .doOnSuccess { saveToCache(it).blockingAwait() }
+                .doOnError {
+                    logError("Cannot load subscriptions from network", it)
+                    logWarn("Getting cached subscriptions")
+                }
+                .onErrorResumeNext(findInCache())
+        } else {
+            findInCache()
+        }
+
+    private fun getFromNetwork(): Single<List<Subscription>> =
+        api.getSubscriptions(auth.getAccessToken())
+
+    private fun findInCache(): Single<List<Subscription>> =
+        cache.getSubscriptions().toSingle()
+
+    private fun saveToCache(subscriptions: List<Subscription>): Completable =
+        cache.saveSubscriptions(subscriptions)
+
+}

+ 2 - 0
app/src/main/java/me/vadik/knigopis/dependency/modules.kt

@@ -42,6 +42,7 @@ val appModule = applicationContext {
             get()
         ) as BookRepository
     }
+    bean { SubscriptionRepositoryImpl(get(), get(), get(), get()) as SubscriptionRepository }
     bean { BookCoverSearchImpl(get(), BookCoverCacheImpl(get())) as BookCoverSearch }
     bean { KAuthImpl(get(), get()) as KAuth }
     bean { createMainEndpoint(get()) }
@@ -52,6 +53,7 @@ val appModule = applicationContext {
     bean { ResourceProviderImpl(get()) as ResourceProvider }
     bean { NetworkCheckerImpl(get()) as NetworkChecker }
     bean { BookCacheImpl(get()) as BookCache }
+    bean { SubscriptionCacheImpl(get()) as SubscriptionCache }
     bean { CommonCacheImpl(get(), get()) as CommonCache }
     bean { GsonBuilder().setDateFormat(DATE_FORMAT).create() }
     factory { BottomSheetDialogFactory(it["activity"]) as DialogFactory }