summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst/feedreader/data/Net.kt
blob: 4d0c956edd514642034df8dcc18e3d5cc2a2fcb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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)
        }
    })
}