summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst/feedreader/data/Net.kt
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-08-22 00:54:33 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-08-22 00:54:33 +0000
commit44b0aa44e065822818e8473bb8e49b0ca45c43c8 (patch)
treef678dc1e43b7432daa009c777c6acbc7201c1f04 /app/src/main/java/org/terst/feedreader/data/Net.kt
parent6373c34525fdac3a298ab5e0299080383b72aaf6 (diff)
Add a cancellable OkHttp Call.await() extension
execute() blocks the calling thread and ignores the coroutine it runs in -- if that coroutine is cancelled (a screen torn down mid-save, a WorkManager-stopped fetch), the network call keeps running to completion regardless, tying up a thread/socket for nothing. enqueue() plus invokeOnCancellation actually aborts the in-flight HTTP call.
Diffstat (limited to 'app/src/main/java/org/terst/feedreader/data/Net.kt')
-rw-r--r--app/src/main/java/org/terst/feedreader/data/Net.kt27
1 files changed, 27 insertions, 0 deletions
diff --git a/app/src/main/java/org/terst/feedreader/data/Net.kt b/app/src/main/java/org/terst/feedreader/data/Net.kt
index d3720a0..4d0c956 100644
--- a/app/src/main/java/org/terst/feedreader/data/Net.kt
+++ b/app/src/main/java/org/terst/feedreader/data/Net.kt
@@ -1,8 +1,35 @@
package org.terst.feedreader.data
+import kotlinx.coroutines.suspendCancellableCoroutine
+import okhttp3.Call
+import okhttp3.Callback
import okhttp3.OkHttpClient
+import okhttp3.Response
+import java.io.IOException
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
/** Shared OkHttp client -- one connection pool for the whole app. */
object Net {
val client: OkHttpClient by lazy { OkHttpClient() }
}
+
+// A plain call.execute() blocks the calling thread and knows nothing about the coroutine
+// it's running inside -- if that coroutine gets cancelled (a screen torn down mid-save, a
+// WorkManager-stopped fetch), the network call keeps right on running to completion
+// regardless, tying up a thread/socket for work nothing is waiting on anymore. enqueue()
+// registers real cancellation: cont.invokeOnCancellation { cancel() } actually aborts the
+// in-flight HTTP call (closes the socket) instead of just abandoning the coroutine.
+suspend fun Call.await(): Response = suspendCancellableCoroutine { cont ->
+ cont.invokeOnCancellation { cancel() }
+ enqueue(object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ cont.resume(response)
+ }
+
+ override fun onFailure(call: Call, e: IOException) {
+ if (cont.isCancelled) return
+ cont.resumeWithException(e)
+ }
+ })
+}