aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt92
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt12
2 files changed, 60 insertions, 44 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt b/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt
index 914ce151..56acfc11 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt
@@ -16,11 +16,14 @@
*/
package com.pitchedapps.frost.kotlin
+import com.pitchedapps.frost.utils.L
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
@@ -64,57 +67,60 @@ class Flyweight<K, V>(
completeExceptionally(result.exceptionOrNull()!!)
}
+ private val errHandler = CoroutineExceptionHandler { _, throwable -> L.d { "FbAuth failed ${throwable.message}" } }
+
init {
- job = scope.launch(Dispatchers.IO) {
- launch {
- while (isActive) {
- select<Unit> {
- /*
- * New request received. Continuation should be fulfilled eventually
- */
- actionChannel.onReceive { (key, completable) ->
- val lastUpdate = conditionMap[key]
- val lastResult = resultMap[key]
- // Valid value, retrieved within acceptable time
- if (lastResult != null && lastUpdate != null && System.currentTimeMillis() - lastUpdate < maxAge) {
- completable.completeWith(lastResult)
- } else {
- val valueRequestPending = key in pendingMap
- pendingMap.getOrPut(key) { mutableListOf() }.add(completable)
- if (!valueRequestPending)
- fulfill(key)
+ job =
+ scope.launch(Dispatchers.IO + SupervisorJob() + errHandler) {
+ launch {
+ while (isActive) {
+ select<Unit> {
+ /*
+ * New request received. Continuation should be fulfilled eventually
+ */
+ actionChannel.onReceive { (key, completable) ->
+ val lastUpdate = conditionMap[key]
+ val lastResult = resultMap[key]
+ // Valid value, retrieved within acceptable time
+ if (lastResult != null && lastUpdate != null && System.currentTimeMillis() - lastUpdate < maxAge) {
+ completable.completeWith(lastResult)
+ } else {
+ val valueRequestPending = key in pendingMap
+ pendingMap.getOrPut(key) { mutableListOf() }.add(completable)
+ if (!valueRequestPending)
+ fulfill(key)
+ }
}
- }
- /*
- * Invalidator received. Existing result associated with key should not be used.
- * Note that any unfulfilled request and future requests should still operate, but with a new value.
- */
- invalidatorChannel.onReceive { key ->
- if (key !in resultMap) {
- // Nothing to invalidate.
- // If pending requests exist, they are already in the process of being updated.
- return@onReceive
+ /*
+ * Invalidator received. Existing result associated with key should not be used.
+ * Note that any unfulfilled request and future requests should still operate, but with a new value.
+ */
+ invalidatorChannel.onReceive { key ->
+ if (key !in resultMap) {
+ // Nothing to invalidate.
+ // If pending requests exist, they are already in the process of being updated.
+ return@onReceive
+ }
+ conditionMap.remove(key)
+ resultMap.remove(key)
+ if (pendingMap[key]?.isNotEmpty() == true)
+ // Refetch value for pending requests
+ fulfill(key)
}
- conditionMap.remove(key)
- resultMap.remove(key)
- if (pendingMap[key]?.isNotEmpty() == true)
- // Refetch value for pending requests
- fulfill(key)
- }
- /*
- * Value request fulfilled. Should now fulfill pending requests
- */
- receiverChannel.onReceive { (key, result) ->
- conditionMap[key] = System.currentTimeMillis()
- resultMap[key] = result
- pendingMap.remove(key)?.forEach {
- it.completeWith(result)
+ /*
+ * Value request fulfilled. Should now fulfill pending requests
+ */
+ receiverChannel.onReceive { (key, result) ->
+ conditionMap[key] = System.currentTimeMillis()
+ resultMap[key] = result
+ pendingMap.remove(key)?.forEach {
+ it.completeWith(result)
+ }
}
}
}
}
}
- }
}
/*
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt
index 860bf36c..9e0b70b2 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt
@@ -27,9 +27,12 @@ import com.pitchedapps.frost.contracts.FrostContentContainer
import com.pitchedapps.frost.contracts.FrostContentCore
import com.pitchedapps.frost.contracts.FrostContentParent
import com.pitchedapps.frost.fragments.RecyclerContentContract
+import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
+import kotlinx.coroutines.supervisorScope
/**
* Created by Allan Wang on 2017-05-29.
@@ -74,7 +77,14 @@ class FrostRecyclerView @JvmOverloads constructor(
if (Prefs.animate) fadeOut(onFinish = onReloadClear)
scope.launch {
parent.refreshChannel.offer(true)
- val loaded = recyclerContract.reload { parent.progressChannel.offer(it) }
+ // TODO figure out how to avoid cancelling parent
+ try {
+ supervisorScope {
+ recyclerContract.reload { parent.progressChannel.offer(it) }
+ }
+ } catch (e: Exception) {
+
+ }
parent.progressChannel.offer(100)
parent.refreshChannel.offer(false)
if (Prefs.animate) circularReveal()