Allow download multiple galleries concurrently

This commit is contained in:
Pupil
2020-02-13 20:07:16 +09:00
parent 842148647f
commit bb63959678
2 changed files with 29 additions and 34 deletions

View File

@@ -19,8 +19,8 @@ android {
applicationId "xyz.quaver.pupil" applicationId "xyz.quaver.pupil"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 41 versionCode 42
versionName "4.5" versionName "4.6-beta1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true

View File

@@ -145,25 +145,21 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
private val loop = loop() private val loop = loop()
private val worker = SparseArray<Job?>() private val worker = SparseArray<Job?>()
@Volatile var nRunners = 0 val clients = SparseArray<OkHttpClient>()
private val client = OkHttpClient.Builder() val interceptor = Interceptor { chain ->
.addInterceptor { chain -> val request = chain.request()
val request = chain.request() val response = chain.proceed(request)
var response = chain.proceed(request)
var retry = preferences.getInt("retry", 3) response.newBuilder()
while (!response.isSuccessful && retry > 0) { .body(ProgressResponseBody(request.tag(), response.body(), progressListener))
response = chain.proceed(request)
retry--
}
response.newBuilder()
.body(ProgressResponseBody(request.tag(), response.body(), progressListener))
.build()
}
.dispatcher(Dispatcher(Executors.newFixedThreadPool(4)))
.build() .build()
}
fun buildClient() =
OkHttpClient.Builder()
.addInterceptor(interceptor)
.dispatcher(Dispatcher(Executors.newFixedThreadPool(4)))
.build()
fun stop() { fun stop() {
queue.clear() queue.clear()
@@ -176,29 +172,30 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
worker[galleryID]?.cancel() worker[galleryID]?.cancel()
} }
client.dispatcher().cancelAll() for (i in 0 until clients.size()) {
clients.valueAt(i).dispatcher().cancelAll()
}
clients.clear()
progress.clear() progress.clear()
exception.clear() exception.clear()
notification.clear() notification.clear()
notificationManager.cancelAll() notificationManager.cancelAll()
nRunners = 0
} }
fun cancel(galleryID: Int) { fun cancel(galleryID: Int) {
queue.remove(galleryID) queue.remove(galleryID)
worker[galleryID]?.cancel() worker[galleryID]?.cancel()
client.dispatcher().queuedCalls() clients[galleryID]?.dispatcher()?.queuedCalls()
.filter { ?.filter {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(it.request().tag() as? Pair<Int, Int>)?.first == galleryID (it.request().tag() as? Pair<Int, Int>)?.first == galleryID
} }
.forEach { ?.forEach {
it.cancel() it.cancel()
} }
clients.remove(galleryID)
progress.remove(galleryID) progress.remove(galleryID)
exception.remove(galleryID) exception.remove(galleryID)
@@ -207,7 +204,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
if (progress.indexOfKey(galleryID) >= 0) { if (progress.indexOfKey(galleryID) >= 0) {
Cache(this@DownloadWorker).setDownloading(galleryID, false) Cache(this@DownloadWorker).setDownloading(galleryID, false)
nRunners--
} }
} }
@@ -240,7 +236,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
tag(galleryID to index) tag(galleryID to index)
}.build() }.build()
client.newCall(request).enqueue(callback) clients[galleryID].newCall(request).enqueue(callback)
} }
private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch { private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch {
@@ -252,7 +248,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
exception.put(galleryID, null) exception.put(galleryID, null)
Cache(this@DownloadWorker).setDownloading(galleryID, false) Cache(this@DownloadWorker).setDownloading(galleryID, false)
nRunners--
return@launch return@launch
} }
@@ -279,11 +274,12 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
setDownloading(galleryID, false) setDownloading(galleryID, false)
} }
} }
nRunners--
return@launch return@launch
} }
clients.put(galleryID, buildClient())
for (i in reader.galleryInfo.indices) { for (i in reader.galleryInfo.indices) {
val callback = object : Callback { val callback = object : Callback {
override fun onFailure(call: Call, e: IOException) { override fun onFailure(call: Call, e: IOException) {
@@ -302,7 +298,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
setDownloading(galleryID, false) setDownloading(galleryID, false)
} }
} }
nRunners-- clients.remove(galleryID)
} }
} }
@@ -325,7 +321,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
setDownloading(galleryID, false) setDownloading(galleryID, false)
} }
} }
nRunners-- clients.remove(galleryID)
} }
} }
} }
@@ -374,19 +370,18 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
private fun loop() = CoroutineScope(Dispatchers.Default).launch { private fun loop() = CoroutineScope(Dispatchers.Default).launch {
while (true) { while (true) {
if (queue.isEmpty() || nRunners > preferences.getInt("max_download", 4)) if (queue.isEmpty() || clients.size() > preferences.getInt("max_download", 4))
continue continue
val galleryID = queue.poll() ?: continue val galleryID = queue.poll() ?: continue
if (progress.indexOfKey(galleryID) >= 0) // Gallery already downloading! if (clients.indexOfKey(galleryID) >= 0) // Gallery already downloading!
continue continue
initNotification(galleryID) initNotification(galleryID)
if (Cache(this@DownloadWorker).isDownloading(galleryID)) if (Cache(this@DownloadWorker).isDownloading(galleryID))
notificationManager.notify(galleryID, notification[galleryID].build()) notificationManager.notify(galleryID, notification[galleryID].build())
worker.put(galleryID, download(galleryID)) worker.put(galleryID, download(galleryID))
nRunners++
} }
} }